Example #1
0
def portfolio_metrics() -> List[
    Union[Union[List[Union[str, Any]], List[str], List[Union[Union[str, float], Any]]], Any]]:
    data = stats.trades(store.completed_trades.trades, store.app.daily_balance)

    metrics = [
        ['Total Closed Trades', data['total']],
        ['Total Net Profit',
         '{} ({})'.format(jh.format_currency(round(data['net_profit'], 4)),
                          str(round(data['net_profit_percentage'], 2)) + '%')],
        ['Starting => Finishing Balance',
         '{} => {}'.format(jh.format_currency(round(data['starting_balance'], 2)),
                           jh.format_currency(round(data['finishing_balance'], 2)))],
        ['Total Open Trades', data['total_open_trades']],
        ['Open PL', jh.format_currency(round(data['open_pl'], 2))],
        ['Total Paid Fees', jh.format_currency(round(data['fee'], 2))],
        ['Max Drawdown', '{}%'.format(round(data['max_drawdown'], 2))],
        ['Annual Return', '{}%'.format(round(data['annual_return'], 2))],
        ['Expectancy',
         '{} ({})'.format(jh.format_currency(round(data['expectancy'], 2)),
                          str(round(data['expectancy_percentage'], 2)) + '%')],
        ['Avg Win | Avg Loss', '{} | {}'.format(jh.format_currency(round(data['average_win'], 2)),
                                                jh.format_currency(round(data['average_loss'], 2)))],
        ['Ratio Avg Win / Avg Loss', round(data['ratio_avg_win_loss'], 2)],
        ['Percent Profitable', str(round(data['win_rate'] * 100)) + '%'],
        ['Longs | Shorts', '{}% | {}%'.format(round(data['longs_percentage']), round(data['short_percentage']))],
        ['Avg Holding Time', jh.readable_duration(data['average_holding_period'], 3)],
        ['Winning Trades Avg Holding Time',
         np.nan if np.isnan(data['average_winning_holding_period']) else jh.readable_duration(
             data['average_winning_holding_period'], 3)],
        ['Losing Trades Avg Holding Time',
         np.nan if np.isnan(data['average_losing_holding_period']) else jh.readable_duration(
             data['average_losing_holding_period'], 3)]
    ]

    if jh.get_config('env.metrics.sharpe_ratio', True):
        metrics.append(['Sharpe Ratio', round(data['sharpe_ratio'], 2)])
    if jh.get_config('env.metrics.calmar_ratio', False):
        metrics.append(['Calmar Ratio', round(data['calmar_ratio'], 2)])
    if jh.get_config('env.metrics.sortino_ratio', False):
        metrics.append(['Sortino Ratio', round(data['sortino_ratio'], 2)])
    if jh.get_config('env.metrics.omega_ratio', False):
        metrics.append(['Omega Ratio', round(data['omega_ratio'], 2)])
    if jh.get_config('env.metrics.winning_streak', False):
        metrics.append(['Winning Streak', data['winning_streak']])
    if jh.get_config('env.metrics.losing_streak', False):
        metrics.append(['Losing Streak', data['losing_streak']])
    if jh.get_config('env.metrics.largest_winning_trade', False):
        metrics.append(['Largest Winning Trade', jh.format_currency(round(data['largest_winning_trade'], 2))])
    if jh.get_config('env.metrics.largest_losing_trade', False):
        metrics.append(['Largest Losing Trade', jh.format_currency(round(data['largest_losing_trade'], 2))])
    if jh.get_config('env.metrics.total_winning_trades', False):
        metrics.append(['Total Winning Trades', data['total_winning_trades']])
    if jh.get_config('env.metrics.total_losing_trades', False):
        metrics.append(['Total Losing Trades', data['total_losing_trades']])

    return metrics
Example #2
0
    def _close(self, close_price: float) -> None:
        if self.is_open is False:
            raise EmptyPosition('The position is already closed.')

        # just to prevent confusion
        close_qty = abs(self.qty)

        estimated_profit = jh.estimate_PNL(close_qty, self.entry_price,
                                           close_price, self.type)
        entry = self.entry_price
        trade_type = self.type
        self.exit_price = close_price

        if self.exchange:
            self.exchange.add_realized_pnl(estimated_profit)
            self.exchange.temp_reduced_amount[jh.base_asset(
                self.symbol)] += abs(close_qty * close_price)
        self.qty = 0
        self.entry_price = None
        self.closed_at = jh.now_to_timestamp()

        if not jh.is_unit_testing():
            info_text = 'CLOSED {} position: {}, {}, {}. PNL: ${}, Balance: ${}, entry: {}, exit: {}'.format(
                trade_type, self.exchange_name, self.symbol,
                self.strategy.name, round(estimated_profit, 2),
                jh.format_currency(
                    round(self.exchange.wallet_balance(self.symbol),
                          2)), entry, close_price)

            if jh.is_debuggable('position_closed'):
                logger.info(info_text)

            if jh.is_live(
            ) and config['env']['notifications']['events']['updated_position']:
                notifier.notify(info_text)
Example #3
0
 def async_save():
     DailyBalance.insert(**daily_balance).execute()
     if jh.is_debugging():
         logger.info('Stored daily portfolio balance record into the database: {} => {}'.format(
             daily_balance['asset'], jh.format_currency(round(daily_balance['balance'], 2))
         ))
Example #4
0
def livetrade():
    # sum up balance of all trading exchanges
    starting_balance = 0
    current_balance = 0
    for e in store.exchanges.storage:
        starting_balance += store.exchanges.storage[e].starting_assets[
            jh.app_currency()]
        current_balance += store.exchanges.storage[e].assets[jh.app_currency()]
    starting_balance = round(starting_balance, 2)
    current_balance = round(current_balance, 2)

    arr = [[
        'started at',
        jh.timestamp_to_arrow(store.app.starting_time).humanize()
    ], ['current time',
        jh.timestamp_to_time(jh.now_to_timestamp())[:19]],
           [
               'errors/info', '{}/{}'.format(len(store.logs.errors),
                                             len(store.logs.info))
           ], ['active orders',
               store.orders.count_all_active_orders()],
           ['open positions',
            store.positions.count_open_positions()]]

    # TODO: for now, we assume that we trade on one exchange only. Later, we need to support for more than one exchange at a time
    first_exchange = selectors.get_exchange(router.routes[0].exchange)

    if first_exchange.type == 'futures':
        arr.append([
            'started/current balance', '{}/{}'.format(starting_balance,
                                                      current_balance)
        ])
    else:
        # loop all trading exchanges
        for exchange in selectors.get_all_exchanges():
            # loop all assets
            for asset_name, asset_balance in exchange.assets.items():
                if asset_name == jh.base_asset(router.routes[0].symbol):
                    current_price = selectors.get_current_price(
                        router.routes[0].exchange, router.routes[0].symbol)
                    arr.append([
                        '{}'.format(asset_name), '{}/{} ({} {})'.format(
                            round(exchange.available_assets[asset_name], 5),
                            round(asset_balance, 5),
                            jh.format_currency(
                                round(asset_balance * current_price, 2)),
                            jh.quote_asset(router.routes[0].symbol))
                    ])
                else:
                    arr.append([
                        '{}'.format(asset_name), '{}/{}'.format(
                            round(exchange.available_assets[asset_name], 5),
                            round(asset_balance, 5),
                        )
                    ])

    # short trades summary
    if len(store.completed_trades.trades):
        df = pd.DataFrame.from_records(
            [t.to_dict() for t in store.completed_trades.trades])
        total = len(df)
        winning_trades = df.loc[df['PNL'] > 0]
        losing_trades = df.loc[df['PNL'] < 0]
        pnl = round(df['PNL'].sum(), 2)
        pnl_percentage = round((pnl / starting_balance) * 100, 2)

        arr.append([
            'total/winning/losing trades',
            '{}/{}/{}'.format(total, len(winning_trades), len(losing_trades))
        ])
        arr.append(['PNL (%)', '${} ({}%)'.format(pnl, pnl_percentage)])

    if config['app']['debug_mode']:
        arr.append(['debug mode', config['app']['debug_mode']])

    if config['app']['is_test_driving']:
        arr.append(['Test Drive', config['app']['is_test_driving']])

    return arr