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
def portfolio_metrics(): data = stats.trades(store.completed_trades.trades, store.app.daily_balance) return [['Total Closed Trades', data['total']], [ 'Total Net Profit', '{} ({})'.format(round(data['net_profit'], 4), str(data['net_profit_percentage']) + '%') ], [ 'Starting => Finishing Balance', '{} => {}'.format(round(data['starting_balance'], 2), round(data['finishing_balance'], 2)) ], ['Total Open Trades', data['total_open_trades']], ['Open PL', round(data['open_pl'], 2)], ['Total Paid Fees', round(data['fee'], 2)], ['Max Drawdown', '{}%'.format(data['max_drawdown'])], ['Sharpe Ratio', data['sharpe_ratio']], ['Annual Return', '{}%'.format(data['annual_return'])], [ 'Expectancy', '{} ({})'.format( round(data['expectancy'], 2), str(round(data['expectancy_percentage'], 2)) + '%') ], [ 'Avg Win | Avg Loss', '{} | {}'.format(round(data['average_win'], 2), 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) ]]
def positions(): """ :return: """ array = [] # headers array.append([ 'type', 'strategy', 'symbol', 'opened at', 'qty', 'entry', 'current price', 'PNL (%)' ]) for p in store.positions.storage: pos = store.positions.storage[p] if pos.pnl_percentage > 0: pnl_color = 'green' elif pos.pnl_percentage < 0: pnl_color = 'red' else: pnl_color = 'black' if pos.type == 'long': type_color = 'green' elif pos.type == 'short': type_color = 'red' else: type_color = 'black' array.append([ jh.color(pos.type, type_color), pos.strategy.name, pos.symbol, '' if pos.is_close else '{} ago'.format( jh.readable_duration((jh.now() - pos.opened_at) / 1000, 3)), pos.qty if abs(pos.qty) > 0 else None, pos.entry_price, pos.current_price, '' if pos.is_close else '{} ({}%)'.format( jh.color(str(round(pos.pnl, 2)), pnl_color), jh.color(str(round(pos.pnl_percentage, 4)), pnl_color)), ]) return array
def test_readable_duration(): assert jh.readable_duration(604312) == "6 days, 23 hours"