Beispiel #1
0
def livetrade():
    # 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
    # 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)

    # 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 = len(df.loc[df['PNL'] > 0])
        losing_trades = len(df.loc[df['PNL'] < 0])
        pnl = round(df['PNL'].sum(), 2)
        pnl_perc = round((pnl / starting_balance) * 100, 2)
    else:
        pnl, pnl_perc, total, winning_trades, losing_trades = 0, 0, 0, 0, 0

    routes = [{
        'exchange': r.exchange,
        'symbol': r.symbol,
        'timeframe': r.timeframe,
        'strategy': r.strategy_name
    } for r in router.routes]

    return {
        'session_id': store.app.session_id,
        'started_at': str(store.app.starting_time),
        'current_time': str(jh.now_to_timestamp()),
        'started_balance': str(starting_balance),
        'current_balance': str(current_balance),
        'debug_mode': str(config['app']['debug_mode']),
        'paper_mode': str(jh.is_paper_trading()),
        'count_error_logs': str(len(store.logs.errors)),
        'count_info_logs': str(len(store.logs.info)),
        'count_active_orders': str(store.orders.count_all_active_orders()),
        'open_positions': str(store.positions.count_open_positions()),
        'pnl': str(pnl),
        'pnl_perc': str(pnl_perc),
        'count_trades': str(total),
        'count_winning_trades': str(winning_trades),
        'count_losing_trades': str(losing_trades),
        'routes': routes
    }
Beispiel #2
0
def test_app_currency():
    from jesse.routes import router
    from jesse.enums import exchanges, timeframes
    router.set_routes([
        (exchanges.BITFINEX, 'ETH-USD', timeframes.HOUR_3, 'Test19'),
    ])
    assert jh.app_currency() == 'USD'
Beispiel #3
0
def save_daily_portfolio_balance() -> None:
    balances = []

    # add exchange balances
    for key, e in store.exchanges.storage.items():
        balances.append(e.assets[jh.app_currency()])

        # store daily_balance of assets into database
        if jh.is_livetrading():
            for asset_key, asset_value in e.assets.items():
                store_daily_balance_into_db({
                    'id':
                    jh.generate_unique_id(),
                    'timestamp':
                    jh.now(),
                    'identifier':
                    jh.get_config('env.identifier', 'main'),
                    'exchange':
                    e.name,
                    'asset':
                    asset_key,
                    'balance':
                    asset_value,
                })

    # add open position values
    for key, pos in store.positions.storage.items():
        if pos.is_open:
            balances.append(pos.pnl)

    total = sum(balances)
    store.app.daily_balance.append(total)
    logger.info('Saved daily portfolio balance: {}'.format(round(total, 2)))
Beispiel #4
0
def tradingview_logs(study_name: str) -> None:
    starting_balance = 0

    for e in store.exchanges.storage:
        starting_balance += store.exchanges.storage[e].starting_assets[
            jh.app_currency()]

    tv_text = f'//@version=4\nstrategy("{study_name}", overlay=true, initial_capital={starting_balance}, commission_type=strategy.commission.percent, commission_value=0.2)\n'
    for i, t in enumerate(store.completed_trades.trades[::-1][:]):
        tv_text += '\n'
        for j, o in enumerate(t.orders):
            when = f"time_close == {int(o.executed_at)}"
            if int(o.executed_at) % (jh.timeframe_to_one_minutes(t.timeframe) *
                                     60_000) != 0:
                when = f"time_close >= {int(o.executed_at)} and time_close - {int(o.executed_at) + jh.timeframe_to_one_minutes(t.timeframe) * 60_000} < {jh.timeframe_to_one_minutes(t.timeframe) * 60_000}"
            if j == len(t.orders) - 1:
                tv_text += f'strategy.close("{i}", when = {when})\n'
            else:
                tv_text += f'strategy.order("{i}", {1 if t.type == "long" else 0}, {abs(o.qty)}, {o.price}, when = {when})\n'

    path = f'storage/trading-view-pine-editor/{study_name}.txt'
    os.makedirs('./storage/trading-view-pine-editor', exist_ok=True)
    with open(path, 'w+') as outfile:
        outfile.write(tv_text)

    print(f'\nPine-editor output saved at: \n{path}')
Beispiel #5
0
def save_daily_portfolio_balance() -> None:
    balances = []

    # add exchange balances
    for key, e in store.exchanges.storage.items():
        balances.append(e.assets[jh.app_currency()])

        # # store daily_balance of assets into database
        # if jh.is_livetrading():
        #     for asset_key, asset_value in e.assets.items():
        #         store_daily_balance_into_db({
        #             'id': jh.generate_unique_id(),
        #             'timestamp': jh.now(),
        #             'identifier': jh.get_config('env.identifier', 'main'),
        #             'exchange': e.name,
        #             'asset': asset_key,
        #             'balance': asset_value,
        #         })

    # add open position values
    for key, pos in store.positions.storage.items():
        if pos.is_open:
            balances.append(pos.pnl)

    total = sum(balances)
    store.app.daily_balance.append(total)

    # TEMP: disable storing in database for now
    if not jh.is_livetrading():
        logger.info(f'Saved daily portfolio balance: {round(total, 2)}')
Beispiel #6
0
def test_app_currency():
    from jesse.routes import router
    from jesse.enums import exchanges, timeframes
    router.initiate([{
        'exchange': exchanges.BITFINEX,
        'symbol': 'ETH-USD',
        'timeframe': timeframes.HOUR_3,
        'strategy': 'Test19'
    }])
    assert jh.app_currency() == 'USD'
Beispiel #7
0
def save_daily_portfolio_balance():
    balances = []

    # add exchange balances
    for key, e in store.exchanges.storage.items():
        balances.append(e.assets[helpers.app_currency()])

    # add open position values
    for key, pos in store.positions.storage.items():
        if pos.is_open:
            balances.append(pos.pnl)

    total = sum(balances)
    store.app.daily_balance.append(total)
    logger.info('Saved daily portfolio balance: {}'.format(round(total, 2)))
Beispiel #8
0
def positions() -> list:
    arr = []

    for r in router.routes:
        if r.strategy is None:
            continue
        p: Position = r.strategy.position
        arr.append({
            'currency': jh.app_currency(),
            'type': p.type,
            'strategy_name': p.strategy.name,
            'symbol': p.symbol,
            'leverage': p.leverage,
            'opened_at': p.opened_at,
            'qty': p.qty,
            'value': round(p.value, 2),
            'entry': p.entry_price,
            'current_price': p.current_price,
            'liq_price': p.liquidation_price,
            'pnl': p.pnl,
            'pnl_perc': p.pnl_percentage
        })

    return arr
Beispiel #9
0
def livetrade() -> List[Union[List[Union[str, Any]], List[str], List[Union[
    str, int]], List[Union[str, Dict[str, Union[str, int]], Dict[
        str, str], Dict[str, bool], Dict[str, Union[Dict[str, Union[
            int, str, List[Dict[str, Union[str, int]]]]], Dict[str, Union[
                float, str, int, List[Dict[str, Union[str, int]]]]]]], Dict[
                    str, int]]]]]:
    # 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', f'{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', f'{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([
                        f'{asset_name}',
                        f'{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([
                        f'{asset_name}',
                        f'{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',
            f'{total}/{len(winning_trades)}/{len(losing_trades)}'
        ])
        arr.append(['PNL (%)', f'${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
Beispiel #10
0
def trades(trades_list: list, daily_balance: list) -> dict:
    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()]

    if len(trades_list) == 0:
        return None

    df = pd.DataFrame.from_records([t.to_dict() for t in trades_list])

    total_completed = len(df)
    winning_trades = df.loc[df['PNL'] > 0]
    total_winning_trades = len(winning_trades)
    losing_trades = df.loc[df['PNL'] < 0]
    total_losing_trades = len(losing_trades)

    arr = df['PNL'].to_numpy()
    pos = np.clip(arr, 0, 1).astype(bool).cumsum()
    neg = np.clip(arr, -1, 0).astype(bool).cumsum()
    current_streak = np.where(
        arr >= 0, pos - np.maximum.accumulate(np.where(arr <= 0, pos, 0)),
        -neg + np.maximum.accumulate(np.where(arr >= 0, neg, 0)))

    s_min = current_streak.min()
    losing_streak = 0 if s_min > 0 else abs(s_min)

    s_max = current_streak.max()
    winning_streak = 0 if s_max < 0 else s_max

    largest_losing_trade = df['PNL'].min()
    largest_winning_trade = df['PNL'].max()

    win_rate = len(winning_trades) / (len(losing_trades) + len(winning_trades))
    max_R = df['R'].max()
    min_R = df['R'].min()
    mean_R = df['R'].mean()
    longs_count = len(df.loc[df['type'] == 'long'])
    shorts_count = len(df.loc[df['type'] == 'short'])
    longs_percentage = longs_count / (longs_count + shorts_count) * 100
    short_percentage = 100 - longs_percentage
    fee = df['fee'].sum()
    net_profit = df['PNL'].sum()
    net_profit_percentage = (net_profit / starting_balance) * 100
    average_win = winning_trades['PNL'].mean()
    average_loss = abs(losing_trades['PNL'].mean())
    ratio_avg_win_loss = average_win / average_loss
    expectancy = (0 if np.isnan(average_win) else average_win) * win_rate - (
        0 if np.isnan(average_loss) else average_loss) * (1 - win_rate)
    expectancy = expectancy
    expectancy_percentage = (expectancy / starting_balance) * 100
    expected_net_profit_every_100_trades = expectancy_percentage * 100
    average_holding_period = df['holding_period'].mean()
    average_winning_holding_period = winning_trades['holding_period'].mean()
    average_losing_holding_period = losing_trades['holding_period'].mean()
    gross_profit = df.loc[df['PNL'] > 0]['PNL'].sum()
    gross_loss = df.loc[df['PNL'] < 0]['PNL'].sum()

    daily_returns = pd.Series(daily_balance).pct_change(1).values
    max_drawdown = crypto_empyrical.max_drawdown(daily_returns) * 100
    annual_return = crypto_empyrical.annual_return(daily_returns) * 100
    sharpe_ratio = crypto_empyrical.sharpe_ratio(daily_returns)
    calmar_ratio = crypto_empyrical.calmar_ratio(daily_returns)
    sortino_ratio = crypto_empyrical.sortino_ratio(daily_returns)
    omega_ratio = crypto_empyrical.omega_ratio(daily_returns)
    total_open_trades = store.app.total_open_trades
    open_pl = store.app.total_open_pl

    return {
        'total':
        np.nan if np.isnan(total_completed) else total_completed,
        'total_winning_trades':
        np.nan if np.isnan(total_winning_trades) else total_winning_trades,
        'total_losing_trades':
        np.nan if np.isnan(total_losing_trades) else total_losing_trades,
        'starting_balance':
        np.nan if np.isnan(starting_balance) else starting_balance,
        'finishing_balance':
        np.nan if np.isnan(current_balance) else current_balance,
        'win_rate':
        np.nan if np.isnan(win_rate) else win_rate,
        'max_R':
        np.nan if np.isnan(max_R) else max_R,
        'min_R':
        np.nan if np.isnan(min_R) else min_R,
        'mean_R':
        np.nan if np.isnan(mean_R) else mean_R,
        'ratio_avg_win_loss':
        np.nan if np.isnan(ratio_avg_win_loss) else ratio_avg_win_loss,
        'longs_count':
        np.nan if np.isnan(longs_count) else longs_count,
        'longs_percentage':
        np.nan if np.isnan(longs_percentage) else longs_percentage,
        'short_percentage':
        np.nan if np.isnan(short_percentage) else short_percentage,
        'shorts_count':
        np.nan if np.isnan(shorts_count) else shorts_count,
        'fee':
        np.nan if np.isnan(fee) else fee,
        'net_profit':
        np.nan if np.isnan(net_profit) else net_profit,
        'net_profit_percentage':
        np.nan if np.isnan(net_profit_percentage) else net_profit_percentage,
        'average_win':
        np.nan if np.isnan(average_win) else average_win,
        'average_loss':
        np.nan if np.isnan(average_loss) else average_loss,
        'expectancy':
        np.nan if np.isnan(expectancy) else expectancy,
        'expectancy_percentage':
        np.nan if np.isnan(expectancy_percentage) else expectancy_percentage,
        'expected_net_profit_every_100_trades':
        np.nan if np.isnan(expected_net_profit_every_100_trades) else
        expected_net_profit_every_100_trades,
        'average_holding_period':
        average_holding_period,
        'average_winning_holding_period':
        average_winning_holding_period,
        'average_losing_holding_period':
        average_losing_holding_period,
        'gross_profit':
        gross_profit,
        'gross_loss':
        gross_loss,
        'max_drawdown':
        max_drawdown,
        'annual_return':
        annual_return,
        'sharpe_ratio':
        sharpe_ratio,
        'calmar_ratio':
        calmar_ratio,
        'sortino_ratio':
        sortino_ratio,
        'omega_ratio':
        omega_ratio,
        'total_open_trades':
        total_open_trades,
        'open_pl':
        open_pl,
        'winning_streak':
        winning_streak,
        'losing_streak':
        losing_streak,
        'largest_losing_trade':
        largest_losing_trade,
        'largest_winning_trade':
        largest_winning_trade,
        'current_streak':
        current_streak[-1],
    }
Beispiel #11
0
def trades(trades_list: list, daily_balance: list):
    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)

    if len(trades_list) == 0:
        return None

    df = pd.DataFrame.from_records([t.to_dict() for t in trades_list])

    total_completed = len(df)
    winning_trades = df.loc[df['PNL'] > 0]
    total_winning_trades = len(winning_trades)
    losing_trades = df.loc[df['PNL'] < 0]
    total_losing_trades = len(losing_trades)

    losing_i = df['PNL'] < 0
    losing_streaks = losing_i.ne(losing_i.shift()).cumsum()
    losing_streak = losing_streaks[losing_i].value_counts().max()

    winning_i = df['PNL'] > 0
    winning_streaks = winning_i.ne(winning_i.shift()).cumsum()
    winning_streak = winning_streaks[winning_i].value_counts().max()
    largest_losing_trade = round(df['PNL'].min(), 2)
    largest_winning_trade = round(df['PNL'].max(), 2)

    win_rate = len(winning_trades) / (len(losing_trades) + len(winning_trades))
    max_R = round(df['R'].max(), 2)
    min_R = round(df['R'].min(), 2)
    mean_R = round(df['R'].mean(), 2)
    longs_count = len(df.loc[df['type'] == 'long'])
    shorts_count = len(df.loc[df['type'] == 'short'])
    longs_percentage = longs_count / (longs_count + shorts_count) * 100
    short_percentage = 100 - longs_percentage
    fee = df['fee'].sum()
    net_profit = round(df['PNL'].sum(), 2)
    net_profit_percentage = round((net_profit / starting_balance) * 100, 2)
    average_win = round(winning_trades['PNL'].mean(), 2)
    average_loss = round(abs(losing_trades['PNL'].mean()), 2)
    ratio_avg_win_loss = average_win / average_loss
    expectancy = (0 if np.isnan(average_win) else average_win) * win_rate - (
        0 if np.isnan(average_loss) else average_loss) * (1 - win_rate)
    expectancy = round(expectancy, 2)
    expectancy_percentage = round((expectancy / starting_balance) * 100, 2)
    expected_net_profit_every_100_trades = round(expectancy_percentage * 100,
                                                 2)
    average_holding_period = df['holding_period'].mean()
    average_winning_holding_period = winning_trades['holding_period'].mean()
    average_losing_holding_period = losing_trades['holding_period'].mean()
    gross_profit = round(df.loc[df['PNL'] > 0]['PNL'].sum(), 2)
    gross_loss = round(df.loc[df['PNL'] < 0]['PNL'].sum(), 2)

    daily_returns = pd.Series(daily_balance).pct_change(1).values
    max_drawdown = round(crypto_empyrical.max_drawdown(daily_returns) * 100, 2)
    annual_return = round(
        crypto_empyrical.annual_return(daily_returns) * 100, 2)
    sharpe_ratio = round(crypto_empyrical.sharpe_ratio(daily_returns), 2)
    calmar_ratio = round(crypto_empyrical.calmar_ratio(daily_returns), 2)
    sortino_ratio = round(crypto_empyrical.sortino_ratio(daily_returns), 2)
    omega_ratio = round(crypto_empyrical.omega_ratio(daily_returns), 2)
    total_open_trades = store.app.total_open_trades
    open_pl = store.app.total_open_pl

    return {
        'total':
        np.nan if np.isnan(total_completed) else total_completed,
        'total_winning_trades':
        np.nan if np.isnan(total_winning_trades) else total_winning_trades,
        'total_losing_trades':
        np.nan if np.isnan(total_losing_trades) else total_losing_trades,
        'starting_balance':
        np.nan if np.isnan(starting_balance) else starting_balance,
        'finishing_balance':
        np.nan if np.isnan(current_balance) else current_balance,
        'win_rate':
        np.nan if np.isnan(win_rate) else win_rate,
        'max_R':
        np.nan if np.isnan(max_R) else max_R,
        'min_R':
        np.nan if np.isnan(min_R) else min_R,
        'mean_R':
        np.nan if np.isnan(mean_R) else mean_R,
        'ratio_avg_win_loss':
        np.nan if np.isnan(ratio_avg_win_loss) else ratio_avg_win_loss,
        'longs_count':
        np.nan if np.isnan(longs_count) else longs_count,
        'longs_percentage':
        np.nan if np.isnan(longs_percentage) else longs_percentage,
        'short_percentage':
        np.nan if np.isnan(short_percentage) else short_percentage,
        'shorts_count':
        np.nan if np.isnan(shorts_count) else shorts_count,
        'fee':
        np.nan if np.isnan(fee) else fee,
        'net_profit':
        np.nan if np.isnan(net_profit) else net_profit,
        'net_profit_percentage':
        np.nan if np.isnan(net_profit_percentage) else net_profit_percentage,
        'average_win':
        np.nan if np.isnan(average_win) else average_win,
        'average_loss':
        np.nan if np.isnan(average_loss) else average_loss,
        'expectancy':
        np.nan if np.isnan(expectancy) else expectancy,
        'expectancy_percentage':
        np.nan if np.isnan(expectancy_percentage) else expectancy_percentage,
        'expected_net_profit_every_100_trades':
        np.nan if np.isnan(expected_net_profit_every_100_trades) else
        expected_net_profit_every_100_trades,
        'average_holding_period':
        average_holding_period,
        'average_winning_holding_period':
        average_winning_holding_period,
        'average_losing_holding_period':
        average_losing_holding_period,
        'gross_profit':
        gross_profit,
        'gross_loss':
        gross_loss,
        'max_drawdown':
        max_drawdown,
        'annual_return':
        annual_return,
        'sharpe_ratio':
        sharpe_ratio,
        'calmar_ratio':
        calmar_ratio,
        'sortino_ratio':
        sortino_ratio,
        'omega_ratio':
        omega_ratio,
        'total_open_trades':
        total_open_trades,
        'open_pl':
        open_pl,
        'winning_streak':
        winning_streak,
        'losing_streak':
        losing_streak,
        'largest_losing_trade':
        largest_losing_trade,
        'largest_winning_trade':
        largest_winning_trade,
    }
Beispiel #12
0
def trades(trades_list: List[CompletedTrade],
           daily_balance: list,
           final: bool = True) -> dict:
    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()]

    if not trades_list:
        return {'total': 0, 'win_rate': 0, 'net_profit_percentage': 0}

    df = pd.DataFrame.from_records([t.to_dict() for t in trades_list])

    total_completed = len(df)
    winning_trades = df.loc[df['PNL'] > 0]
    total_winning_trades = len(winning_trades)
    losing_trades = df.loc[df['PNL'] < 0]
    total_losing_trades = len(losing_trades)

    arr = df['PNL'].to_numpy()
    pos = np.clip(arr, 0, 1).astype(bool).cumsum()
    neg = np.clip(arr, -1, 0).astype(bool).cumsum()
    current_streak = np.where(
        arr >= 0, pos - np.maximum.accumulate(np.where(arr <= 0, pos, 0)),
        -neg + np.maximum.accumulate(np.where(arr >= 0, neg, 0)))

    s_min = current_streak.min()
    losing_streak = 0 if s_min > 0 else abs(s_min)

    s_max = current_streak.max()
    winning_streak = max(s_max, 0)

    largest_losing_trade = 0 if total_losing_trades == 0 else losing_trades[
        'PNL'].min()
    largest_winning_trade = 0 if total_winning_trades == 0 else winning_trades[
        'PNL'].max()

    win_rate = len(winning_trades) / (len(losing_trades) + len(winning_trades))
    longs_count = len(df.loc[df['type'] == 'long'])
    shorts_count = len(df.loc[df['type'] == 'short'])
    longs_percentage = longs_count / (longs_count + shorts_count) * 100
    shorts_percentage = 100 - longs_percentage
    fee = df['fee'].sum()
    net_profit = df['PNL'].sum()
    net_profit_percentage = (net_profit / starting_balance) * 100
    average_win = winning_trades['PNL'].mean()
    average_loss = abs(losing_trades['PNL'].mean())
    ratio_avg_win_loss = average_win / average_loss
    expectancy = (0 if np.isnan(average_win) else average_win) * win_rate - (
        0 if np.isnan(average_loss) else average_loss) * (1 - win_rate)
    expectancy = expectancy
    expectancy_percentage = (expectancy / starting_balance) * 100
    expected_net_profit_every_100_trades = expectancy_percentage * 100
    average_holding_period = df['holding_period'].mean()
    average_winning_holding_period = winning_trades['holding_period'].mean()
    average_losing_holding_period = losing_trades['holding_period'].mean()
    gross_profit = winning_trades['PNL'].sum()
    gross_loss = losing_trades['PNL'].sum()

    start_date = datetime.fromtimestamp(store.app.starting_time / 1000)
    date_index = pd.date_range(start=start_date, periods=len(daily_balance))

    daily_return = pd.DataFrame(daily_balance, index=date_index).pct_change(1)

    total_open_trades = store.app.total_open_trades
    open_pl = store.app.total_open_pl

    max_drawdown = np.nan
    annual_return = np.nan
    sharpe_ratio = np.nan
    calmar_ratio = np.nan
    sortino_ratio = np.nan
    omega_ratio = np.nan
    serenity_index = np.nan
    smart_sharpe = np.nan
    smart_sortino = np.nan

    if len(daily_return) > 2:
        max_drawdown = stats.max_drawdown(daily_return).values[0] * 100
        annual_return = stats.cagr(daily_return).values[0] * 100
        sharpe_ratio = stats.sharpe(daily_return, periods=365).values[0]
        calmar_ratio = stats.calmar(daily_return).values[0]
        sortino_ratio = stats.sortino(daily_return, periods=365).values[0]
        omega_ratio = stats.omega(daily_return, periods=365)
        serenity_index = stats.serenity_index(daily_return).values[0]
        # As those calculations are slow they are only done for the final report and not at self.metrics in the strategy.
        if final:
            smart_sharpe = stats.smart_sharpe(daily_return,
                                              periods=365).values[0]
            smart_sortino = stats.smart_sortino(daily_return,
                                                periods=365).values[0]

    return {
        'total':
        np.nan if np.isnan(total_completed) else total_completed,
        'total_winning_trades':
        np.nan if np.isnan(total_winning_trades) else total_winning_trades,
        'total_losing_trades':
        np.nan if np.isnan(total_losing_trades) else total_losing_trades,
        'starting_balance':
        np.nan if np.isnan(starting_balance) else starting_balance,
        'finishing_balance':
        np.nan if np.isnan(current_balance) else current_balance,
        'win_rate':
        np.nan if np.isnan(win_rate) else win_rate,
        'ratio_avg_win_loss':
        np.nan if np.isnan(ratio_avg_win_loss) else ratio_avg_win_loss,
        'longs_count':
        np.nan if np.isnan(longs_count) else longs_count,
        'longs_percentage':
        np.nan if np.isnan(longs_percentage) else longs_percentage,
        'shorts_percentage':
        np.nan if np.isnan(shorts_percentage) else shorts_percentage,
        'shorts_count':
        np.nan if np.isnan(shorts_count) else shorts_count,
        'fee':
        np.nan if np.isnan(fee) else fee,
        'net_profit':
        np.nan if np.isnan(net_profit) else net_profit,
        'net_profit_percentage':
        np.nan if np.isnan(net_profit_percentage) else net_profit_percentage,
        'average_win':
        np.nan if np.isnan(average_win) else average_win,
        'average_loss':
        np.nan if np.isnan(average_loss) else average_loss,
        'expectancy':
        np.nan if np.isnan(expectancy) else expectancy,
        'expectancy_percentage':
        np.nan if np.isnan(expectancy_percentage) else expectancy_percentage,
        'expected_net_profit_every_100_trades':
        np.nan if np.isnan(expected_net_profit_every_100_trades) else
        expected_net_profit_every_100_trades,
        'average_holding_period':
        average_holding_period,
        'average_winning_holding_period':
        average_winning_holding_period,
        'average_losing_holding_period':
        average_losing_holding_period,
        'gross_profit':
        gross_profit,
        'gross_loss':
        gross_loss,
        'max_drawdown':
        np.nan if np.isnan(max_drawdown) else max_drawdown,
        'annual_return':
        np.nan if np.isnan(annual_return) else annual_return,
        'sharpe_ratio':
        np.nan if np.isnan(sharpe_ratio) else sharpe_ratio,
        'calmar_ratio':
        np.nan if np.isnan(calmar_ratio) else calmar_ratio,
        'sortino_ratio':
        np.nan if np.isnan(sortino_ratio) else sortino_ratio,
        'omega_ratio':
        np.nan if np.isnan(omega_ratio) else omega_ratio,
        'serenity_index':
        np.nan if np.isnan(serenity_index) else serenity_index,
        'smart_sharpe':
        np.nan if np.isnan(smart_sharpe) else smart_sharpe,
        'smart_sortino':
        np.nan if np.isnan(smart_sortino) else smart_sortino,
        'total_open_trades':
        total_open_trades,
        'open_pl':
        open_pl,
        'winning_streak':
        winning_streak,
        'losing_streak':
        losing_streak,
        'largest_losing_trade':
        largest_losing_trade,
        'largest_winning_trade':
        largest_winning_trade,
        'current_streak':
        current_streak[-1],
    }