def single_route_backtest(strategy_name: str, is_futures_trading=True, leverage=1, leverage_mode='cross', trend='up'): """ used to simplify simple tests """ set_up(is_futures_trading=is_futures_trading, leverage=leverage, leverage_mode=leverage_mode) routes = [{ 'exchange': exchanges.SANDBOX, 'symbol': 'BTC-USDT', 'timeframe': '1m', 'strategy': strategy_name }] if trend == 'up': candles = get_btc_candles() elif trend == 'down': candles = get_downtrend_candles() else: raise ValueError # dates are fake. just to pass required parameters backtest_mode.run(False, {}, routes, [], '2019-04-01', '2019-04-02', candles)
def test_backtesting_three_routes(): reset_config() router.set_routes([ (exchanges.SANDBOX, 'BTCUSD', timeframes.MINUTE_5, 'Test19'), (exchanges.SANDBOX, 'ETHUSD', timeframes.MINUTE_5, 'Test19'), (exchanges.SANDBOX, 'XRPUSD', timeframes.MINUTE_15, 'Test19'), ]) store.reset(True) candles = {} routes = router.routes for r in routes: key = jh.key(r.exchange, r.symbol) candles[key] = { 'exchange': r.exchange, 'symbol': r.symbol, 'candles': fake_range_candle(5 * 3 * 20) } # assert that strategy hasn't been initiated before running backtest_mode() assert r.strategy is None # run backtest (dates are fake just to pass) backtest_mode.run('2019-04-01', '2019-04-02', candles) # there must be three positions present with the updated current_price assert len(store.positions.storage) == 3 for r in routes: # r3's '15m' timeframe makes r1 and r2 to support # '15' timeframe as well. r1 and r2 also make r3 # to support '5m' timeframe also. r_one_min = store.candles.get_candles(r.exchange, r.symbol, '1m') r_five_min = store.candles.get_candles(r.exchange, r.symbol, '5m') r_fifteen_min = store.candles.get_candles(r.exchange, r.symbol, '15m') # assert the count of present candles assert len(r_one_min) == (5 * 3) * 20 assert len(r_five_min) == 20 * 3 assert len(r_fifteen_min) == 20 r_first_1 = r_one_min[0] r_last_1 = r_one_min[-1] r_first_5 = r_five_min[0] r_last_5 = r_five_min[-1] r_first_15 = r_fifteen_min[0] r_last_15 = r_fifteen_min[-1] # assert timestamps assert r_first_1[0] == r_first_5[0] assert r_last_1[0] == (r_last_5[0] + 60000 * 4) assert r_last_5[0] == (r_last_15[0] + 60000 * 10) # assert positions p = selectors.get_position(r.exchange, r.symbol) assert p.is_close is True last_candle = store.candles.get_candles(r.exchange, r.symbol, '1m')[-1] assert p.current_price == last_candle[2] # assert that the strategy has been initiated assert r.strategy is not None
def test_portfolio_value(): set_up() routes = [ { 'exchange': exchanges.SANDBOX, 'symbol': 'ETH-USDT', 'timeframe': '5m', 'strategy': 'TestPortfolioValue' }, { 'exchange': exchanges.SANDBOX, 'symbol': 'BTC-USDT', 'timeframe': '5m', 'strategy': 'TestPortfolioValue' }, ] candles = {} for r in routes: key = jh.key(r['exchange'], r['symbol']) candles[key] = { 'exchange': r['exchange'], 'symbol': r['symbol'], 'candles': range_candles((5 * 3) * 20) } # run backtest (dates are fake just to pass) backtest_mode.run(False, {}, routes, [], '2019-04-01', '2019-04-02', candles)
def test_modifying_stop_loss_after_part_of_position_is_already_reduced_with_stop_loss( ): set_up([ (exchanges.SANDBOX, 'BTCUSD', timeframes.MINUTE_1, 'Test14'), ]) generated_candles = fake_range_candle_from_range_prices( list(range(1, 10)) + list(range(10, 1, -1))) candles = {} key = jh.key(exchanges.SANDBOX, 'BTCUSD') candles[key] = { 'exchange': exchanges.SANDBOX, 'symbol': 'BTCUSD', 'candles': generated_candles } backtest_mode.run('2019-04-01', '2019-04-02', candles) assert len(store.completed_trades.trades) == 1 t1: CompletedTrade = store.completed_trades.trades[0] assert t1.type == 'long' assert t1.entry_price == 7 assert t1.exit_price == (4 * 2 + 6) / 3 assert t1.take_profit_at == 13 assert t1.stop_loss_at == (4 * 2 + 6) / 3 assert t1.qty == 1.5 assert t1.fee == 0
def single_route_backtest(strategy_name: str, is_margin_trading=True): """ used to simplify simple tests """ set_up([(exchanges.SANDBOX, 'BTC-USDT', timeframes.MINUTE_1, strategy_name)], is_margin_trading=is_margin_trading) # dates are fake. just to pass required parameters backtest_mode.run('2019-04-01', '2019-04-02', get_btc_candles())
def test_strategy_properties(): set_up([ (exchanges.SANDBOX, 'ETHUSDT', timeframes.MINUTE_5, 'Test19'), (exchanges.SANDBOX, 'BTCUSDT', timeframes.MINUTE_5, 'Test19'), ]) candles = {} routes = router.routes for r in routes: key = jh.key(r.exchange, r.symbol) candles[key] = { 'exchange': r.exchange, 'symbol': r.symbol, 'candles': fake_range_candle((5 * 3) * 20) } # run backtest (dates are fake just to pass) backtest_mode.run('2019-04-01', '2019-04-02', candles) for r in routes: s: Strategy = r.strategy assert s.name == r.strategy_name assert s.symbol == r.symbol assert s.exchange == r.exchange assert s.timeframe == r.timeframe assert s.trade is None assert s._is_executing is False assert s._is_initiated is True np.testing.assert_equal(s.current_candle, store.candles.get_current_candle(r.exchange, r.symbol, r.timeframe)) np.testing.assert_equal(s.candles, store.candles.get_candles(r.exchange, r.symbol, r.timeframe)) assert s.position == selectors.get_position(r.exchange, r.symbol) assert s.orders == store.orders.get_orders(r.exchange, r.symbol)
def backtest(start_date: str, finish_date: str, debug: bool, csv: bool, json: bool, fee: bool, chart: bool, tradingview: bool, full_reports: bool) -> None: """ backtest mode. Enter in "YYYY-MM-DD" "YYYY-MM-DD" """ validate_cwd() from jesse.config import config config['app']['trading_mode'] = 'backtest' register_custom_exception_handler() from jesse.services import db from jesse.modes import backtest_mode from jesse.services.selectors import get_exchange # debug flag config['app']['debug_mode'] = debug # fee flag if not fee: for e in config['app']['trading_exchanges']: config['env']['exchanges'][e]['fee'] = 0 get_exchange(e).fee = 0 backtest_mode.run(start_date, finish_date, chart=chart, tradingview=tradingview, csv=csv, json=json, full_reports=full_reports) db.close_connection()
def two_routes_backtest(strategy_name1: str, strategy_name2: str, is_futures_trading=True, leverage=1, leverage_mode='cross', trend='up'): """ used to simplify simple tests """ set_up(is_futures_trading=is_futures_trading, leverage=leverage, leverage_mode=leverage_mode) routes = [ { 'exchange': exchanges.SANDBOX, 'symbol': 'BTC-USDT', 'timeframe': '1m', 'strategy': strategy_name1 }, { 'exchange': exchanges.SANDBOX, 'symbol': 'ETH-USDT', 'timeframe': '1m', 'strategy': strategy_name2 }, ] # dates are fake. just to pass required parameters backtest_mode.run(False, {}, routes, [], '2019-04-01', '2019-04-02', get_btc_and_eth_candles())
def test_modifying_stop_loss_after_part_of_position_is_already_reduced_with_stop_loss( ): set_up() routes = [{ 'exchange': exchanges.SANDBOX, 'symbol': 'BTC-USDT', 'timeframe': timeframes.MINUTE_1, 'strategy': 'Test14' }] generated_candles = candles_from_close_prices( list(range(1, 10)) + list(range(10, 1, -1))) candles = {} key = jh.key(exchanges.SANDBOX, 'BTC-USDT') candles[key] = { 'exchange': exchanges.SANDBOX, 'symbol': 'BTC-USDT', 'candles': generated_candles } backtest_mode.run(False, {}, routes, [], '2019-04-01', '2019-04-02', candles) assert len(store.completed_trades.trades) == 1 t1: CompletedTrade = store.completed_trades.trades[0] assert t1.type == 'long' assert t1.entry_price == 7 assert t1.exit_price == (4 * 2 + 6) / 3 assert t1.qty == 1.5 assert t1.fee == 0
def test_can_handle_multiple_entry_orders_too_close_to_each_other(): set_up([ (exchanges.SANDBOX, 'BTC-USDT', timeframes.MINUTE_1, 'Test34'), ]) backtest_mode.run('2019-04-01', '2019-04-02', get_btc_candles()) assert len(store.completed_trades.trades) == 1 t: CompletedTrade = store.completed_trades.trades[0] assert t.type == 'long' assert t.stop_loss_at == 0.4 assert t.entry_price == (1.1 + 1.2 + 1.3 + 1.4) / 4 assert t.exit_price == 3 assert t.take_profit_at == 3 # 4 entry + 1 exit assert len(t.orders) == 5 # last order is closing order assert t.orders[-1].role == order_roles.CLOSE_POSITION # first order must be opening order assert t.orders[0].role == order_roles.OPEN_POSITION # second order must be increasing order assert t.orders[1].role == order_roles.INCREASE_POSITION assert t.orders[2].role == order_roles.INCREASE_POSITION
def test_forming_candles(): reset_config() routes = [{ 'exchange': exchanges.SANDBOX, 'symbol': 'BTC-USDT', 'timeframe': timeframes.MINUTE_5, 'strategy': 'Test19' }] extra_routes = [{ 'exchange': exchanges.SANDBOX, 'symbol': 'BTC-USDT', 'timeframe': timeframes.MINUTE_15 }] candles = {} key = jh.key(exchanges.SANDBOX, 'BTC-USDT') candles[key] = { 'exchange': exchanges.SANDBOX, 'symbol': 'BTC-USDT', 'candles': test_candles_0 } backtest_mode.run(False, {}, routes, extra_routes, '2019-04-01', '2019-04-02', candles) # use math.ceil because it must include forming candle too assert len( store.candles.get_candles(exchanges.SANDBOX, 'BTC-USDT', timeframes.MINUTE_5)) == math.ceil(1382 / 5) assert len( store.candles.get_candles(exchanges.SANDBOX, 'BTC-USDT', timeframes.MINUTE_15)) == math.ceil(1382 / 15)
def test_on_route_increased_position_and_on_route_reduced_position_and_strategy_vars( ): set_up([ (exchanges.SANDBOX, 'BTC-USDT', timeframes.MINUTE_1, 'Test29'), (exchanges.SANDBOX, 'ETH-USDT', timeframes.MINUTE_1, 'Test30'), ]) backtest_mode.run('2019-04-01', '2019-04-02', get_btc_and_eth_candles()) # long BTC-USD t1 = store.completed_trades.trades[0] # short BTC-USD t2 = store.completed_trades.trades[1] # long ETH-USD t3 = store.completed_trades.trades[2] assert t1.symbol == 'BTC-USDT' assert t1.type == 'long' assert t1.entry_price == 121 assert t1.exit_price == 131 assert t1.qty == 1 assert t2.symbol == 'BTC-USDT' assert t2.type == 'short' assert t2.entry_price == 151 assert t2.exit_price == 161 assert t2.qty == 1 assert t3.symbol == 'ETH-USDT' assert t3.type == 'long' # because we open at 10, and increase at 20, entry is the mean which is 15 assert t3.entry_price == 15 # (50 + 70) / 2 assert t3.exit_price == 60 assert t3.qty == 2
def test_on_route_take_profit(): set_up([ (exchanges.SANDBOX, 'BTC-USDT', timeframes.MINUTE_1, 'Test23'), (exchanges.SANDBOX, 'ETH-USDT', timeframes.MINUTE_1, 'Test24'), ]) backtest_mode.run('2019-04-01', '2019-04-02', get_btc_and_eth_candles()) t1 = store.completed_trades.trades[0] t2 = store.completed_trades.trades[1] assert t2.symbol == 'BTC-USDT' assert t2.type == 'long' assert t2.entry_price == 101 assert t2.exit_price == 120 assert t2.take_profit_at == 120 assert t2.qty == 1 assert np.isnan(t2.stop_loss_at) assert t1.symbol == 'ETH-USDT' assert t1.type == 'long' assert t1.entry_price == 10 assert t1.exit_price == 20 assert t1.take_profit_at == 20 assert t1.qty == 1 assert np.isnan(t1.stop_loss_at)
def test_forming_candles(): reset_config() router.set_routes([(exchanges.SANDBOX, 'BTC-USDT', timeframes.MINUTE_5, 'Test19')]) router.set_extra_candles([(exchanges.SANDBOX, 'BTC-USDT', timeframes.MINUTE_15)]) store.reset(True) candles = {} key = jh.key(exchanges.SANDBOX, 'BTC-USDT') candles[key] = { 'exchange': exchanges.SANDBOX, 'symbol': 'BTC-USDT', 'candles': test_candles_0 } backtest_mode.run('2019-04-01', '2019-04-02', candles) # use math.ceil because it must include forming candle too assert len( store.candles.get_candles(exchanges.SANDBOX, 'BTC-USDT', timeframes.MINUTE_5)) == math.ceil(1382 / 5) assert len( store.candles.get_candles(exchanges.SANDBOX, 'BTC-USDT', timeframes.MINUTE_15)) == math.ceil(1382 / 15)
def test_open_pl_and_total_open_trades(): set_up([(exchanges.SANDBOX, 'BTCUSDT', '1m', 'Test40')]) backtest_mode.run('2019-04-01', '2019-04-02', get_btc_candles()) assert len(store.completed_trades.trades) == 1 assert store.app.total_open_trades == 1 assert store.app.total_open_pl == 97 # 99 - 2
def test_backtesting_one_route(): reset_config() router.set_routes([ (exchanges.SANDBOX, 'BTC-USDT', timeframes.MINUTE_5, 'Test19') ]) config['env']['exchanges'][exchanges.SANDBOX]['type'] = 'margin' store.reset(True) candles = {} key = jh.key(exchanges.SANDBOX, 'BTC-USDT') candles[key] = { 'exchange': exchanges.SANDBOX, 'symbol': 'BTC-USDT', 'candles': fake_range_candle(5 * 20) } routes = router.routes # assert that strategy hasn't been initiated before running backtest_mode() assert routes[0].strategy is None # run backtest (dates are fake just to pass) backtest_mode.run('2019-04-01', '2019-04-02', candles) one_min = store.candles.get_candles(exchanges.SANDBOX, 'BTC-USDT', '1m') five_min = store.candles.get_candles(exchanges.SANDBOX, 'BTC-USDT', '5m') # assert the count of present candles assert len(five_min) == 20 assert len(one_min) == 20 * 5 first_1 = one_min[0] last_1 = one_min[-1] first_5 = five_min[0] last_5 = five_min[-1] # assert time in store assert store.app.time == last_1[0] + 60000 # assert timestamps assert first_1[0] == first_5[0] assert last_1[0] == (last_5[0] + 60000 * 4) # there must be only one positions present assert len(store.positions.storage) == 1 p = selectors.get_position(exchanges.SANDBOX, 'BTC-USDT') assert p.is_close assert p.current_price == last_1[2] assert p.current_price == last_5[2] # assert routes assert len(routes) == 1 assert routes[0].exchange == exchanges.SANDBOX assert routes[0].symbol == 'BTC-USDT' assert routes[0].timeframe == '5m' assert routes[0].strategy_name == 'Test19' # assert that the strategy has been initiated assert routes[0].strategy is not None
def test_multiple_routes_can_communicate_with_each_other(): set_up() routes = [ { 'exchange': exchanges.SANDBOX, 'symbol': 'ETH-USDT', 'timeframe': '5m', 'strategy': 'Test03' }, { 'exchange': exchanges.SANDBOX, 'symbol': 'BTC-USDT', 'timeframe': '5m', 'strategy': 'Test03' }, ] candles = {} for r in routes: key = jh.key(r['exchange'], r['symbol']) candles[key] = { 'exchange': r['exchange'], 'symbol': r['symbol'], 'candles': range_candles((5 * 3) * 20) } # run backtest (dates are fake just to pass) backtest_mode.run(False, {}, routes, [], '2019-04-01', '2019-04-02', candles) assert len(store.completed_trades.trades) == 1 for r in router.routes: s: Strategy = r.strategy p = s.position assert p.is_close is True o: Order = s.orders[0] short_candles = store.candles.get_candles(r.exchange, r.symbol, '1m') assert o.created_at == short_candles[4][0] + 60_000 if r.strategy.trades_count == 0: assert len(s.orders) == 1 # assert that the order got canceled assert o.is_canceled is True assert s.orders[0].role == order_roles.OPEN_POSITION assert s.orders[0].type == order_types.LIMIT elif r.strategy.trades_count == 1: assert len(s.orders) == 3 assert o.is_executed is True assert s.orders[0].role == order_roles.OPEN_POSITION assert s.orders[0].type == order_types.LIMIT assert s.orders[2].role == order_roles.CLOSE_POSITION assert s.orders[2].type == order_types.STOP assert s.orders[1].role == order_roles.CLOSE_POSITION assert s.orders[1].type == order_types.LIMIT
def test_can_perform_backtest_with_multiple_routes(): set_up() routes = [ { 'exchange': exchanges.SANDBOX, 'symbol': 'ETH-USDT', 'timeframe': '5m', 'strategy': 'Test01' }, { 'exchange': exchanges.SANDBOX, 'symbol': 'BTC-USDT', 'timeframe': '5m', 'strategy': 'Test02' }, ] candles = {} for r in routes: key = jh.key(r['exchange'], r['symbol']) candles[key] = { 'exchange': r['exchange'], 'symbol': r['symbol'], 'candles': range_candles((5 * 3) * 20) } # run backtest (dates are fake just to pass) backtest_mode.run(False, {}, routes, [], '2019-04-01', '2019-04-02', candles) for r in router.routes: s: Strategy = r.strategy p = s.position assert p.is_close is True assert len(s.orders) == 3 o: Order = s.orders[0] short_candles = store.candles.get_candles(r.exchange, r.symbol, '1m') assert o.price == short_candles[4][2] assert o.price == s.candles[0][2] assert o.created_at == short_candles[4][0] + 60_000 assert o.is_executed is True assert s.orders[0].role == order_roles.OPEN_POSITION assert s.orders[0].type == order_types.MARKET assert s.orders[2].role == order_roles.CLOSE_POSITION assert s.orders[2].type == order_types.STOP assert s.orders[1].role == order_roles.CLOSE_POSITION assert s.orders[1].type == order_types.LIMIT assert s.trade is None assert len(store.completed_trades.trades) == 2 # assert one is long and the other is a short trade assert (store.completed_trades.trades[0].type == 'long' and store.completed_trades.trades[1].type == 'short') or ( store.completed_trades.trades[0].type == 'short' and store.completed_trades.trades[1].type == 'long')
def test_conflicting_orders_2(): set_up([ (exchanges.SANDBOX, 'BTC-USDT', timeframes.MINUTE_1, 'Test20'), ]) backtest_mode.run('2019-04-01', '2019-04-02', get_btc_candles()) assert len(store.completed_trades.trades) == 1 t: CompletedTrade = store.completed_trades.trades[0] assert t.entry_price == 2.5 assert t.exit_price == 2.6
def test_opening_position_in_multiple_points(): set_up([ (exchanges.SANDBOX, 'BTC-USDT', timeframes.MINUTE_1, 'Test15'), ]) backtest_mode.run('2019-04-01', '2019-04-02', get_btc_candles()) assert len(store.completed_trades.trades) == 1 t1: CompletedTrade = store.completed_trades.trades[0] assert t1.type == 'long' assert t1.entry_price == (7 + 9 + 11) / 3 assert t1.exit_price == 15 assert t1.qty == 1.5 assert t1.fee == 0
def test_modifying_take_profit_after_opening_position(): set_up([ (exchanges.SANDBOX, 'BTC-USDT', timeframes.MINUTE_5, 'Test12'), ]) backtest_mode.run('2019-04-01', '2019-04-02', get_btc_candles()) assert len(store.completed_trades.trades) == 1 t1: CompletedTrade = store.completed_trades.trades[0] assert t1.type == 'long' assert t1.entry_price == 7 assert t1.exit_price == 16 assert t1.qty == 1.5 assert t1.fee == 0
def test_should_buy_and_execute_buy(): set_up() routes = [ { 'exchange': exchanges.SANDBOX, 'symbol': 'ETH-USDT', 'timeframe': timeframes.MINUTE_5, 'strategy': 'Test01' }, ] candles = {} for r in routes: key = jh.key(r['exchange'], r['symbol']) candles[key] = { 'exchange': r['exchange'], 'symbol': r['symbol'], 'candles': range_candles((5 * 3) * 20) } # run backtest (dates are fake just to pass) backtest_mode.run(False, {}, routes, [], '2019-04-01', '2019-04-02', candles) for r in router.routes: s: Strategy = r.strategy p = s.position assert p.is_close is True assert len(s.orders) == 3 o: Order = s.orders[0] short_candles = store.candles.get_candles(r.exchange, r.symbol, '1m') assert o.price == short_candles[4][2] assert o.price == s.candles[0][2] assert o.created_at == short_candles[4][0] + 60_000 assert o.is_executed is True assert s.orders[1].role == order_roles.CLOSE_POSITION assert s.orders[2].role == order_roles.CLOSE_POSITION assert s.orders[0].role == order_roles.OPEN_POSITION assert s.trade is None trade: CompletedTrade = store.completed_trades.trades[0] assert trade.type == 'long' # must include executed orders, in this case it's entry and take_profit assert len(trade.orders) == 2 assert trade.orders[0].side == 'buy' assert trade.orders[0].type == 'MARKET' assert trade.orders[1].side == 'sell' assert trade.orders[1].type == 'LIMIT' assert len(store.completed_trades.trades) == 1
def test_stop_loss_at_multiple_points(): set_up([ (exchanges.SANDBOX, 'BTC-USDT', timeframes.MINUTE_1, 'Test11'), ]) backtest_mode.run('2019-04-01', '2019-04-02', get_btc_candles()) assert len(store.completed_trades.trades) == 1 t1: CompletedTrade = store.completed_trades.trades[0] assert t1.type == 'short' assert t1.entry_price == 3 assert t1.exit_price == (6 + 5 + 4) / 3 assert t1.qty == 1.5 assert t1.fee == 0
def test_reducing_position_size_after_opening(): set_up([ (exchanges.SANDBOX, 'BTC-USDT', timeframes.MINUTE_1, 'Test17'), ]) backtest_mode.run('2019-04-01', '2019-04-02', get_btc_candles()) assert len(store.completed_trades.trades) == 1 t1: CompletedTrade = store.completed_trades.trades[0] assert t1.type == 'long' assert t1.entry_price == 7 assert t1.exit_price == (15 + 10) / 2 assert t1.qty == 2 assert t1.fee == 0
def test_on_route_canceled(): set_up([ (exchanges.SANDBOX, 'BTC-USDT', timeframes.MINUTE_1, 'Test27'), (exchanges.SANDBOX, 'ETH-USDT', timeframes.MINUTE_1, 'Test28'), ]) backtest_mode.run('2019-04-01', '2019-04-02', get_btc_and_eth_candles()) t1 = store.completed_trades.trades[0] assert t1.symbol == 'BTC-USDT' assert t1.type == 'long' assert t1.entry_price == 101 assert t1.exit_price == 120 assert t1.qty == 1
def test_shared_vars(): set_up([ (exchanges.SANDBOX, 'BTC-USDT', timeframes.MINUTE_1, 'Test32'), (exchanges.SANDBOX, 'ETH-USDT', timeframes.MINUTE_1, 'Test33'), ]) backtest_mode.run('2019-04-01', '2019-04-02', get_btc_and_eth_candles()) t1 = store.completed_trades.trades[0] assert t1.symbol == 'ETH-USDT' assert t1.type == 'long' assert t1.entry_price == 11 assert t1.exit_price == 21 assert t1.qty == 1
def test_taking_profit_at_multiple_points(): set_up([ (exchanges.SANDBOX, 'BTC-USDT', timeframes.MINUTE_5, 'Test10'), ]) backtest_mode.run('2019-04-01', '2019-04-02', get_btc_candles()) assert len(store.completed_trades.trades) == 1 t1: CompletedTrade = store.completed_trades.trades[0] assert t1.type == 'long' assert t1.entry_price == 7 assert t1.exit_price == (15 + 13 + 11) / 3 assert t1.qty == 1.5 assert t1.fee == 0 assert t1.holding_period == 8 * 60
def test_modifying_take_profit_after_part_of_position_is_already_reduced_with_profit( ): set_up([ (exchanges.SANDBOX, 'BTC-USDT', timeframes.MINUTE_1, 'Test13'), ]) backtest_mode.run('2019-04-01', '2019-04-02', get_btc_candles()) assert len(store.completed_trades.trades) == 1 t1: CompletedTrade = store.completed_trades.trades[0] assert t1.type == 'long' assert t1.entry_price == 7 assert t1.exit_price == (16 * 2 + 11) / 3 assert t1.qty == 1.5 assert t1.fee == 0
def test_conflicting_orders(): set_up([ (exchanges.SANDBOX, 'BTC-USDT', timeframes.MINUTE_1, 'Test04'), ]) backtest_mode.run('2019-04-01', '2019-04-02', get_btc_candles()) assert len(store.completed_trades.trades) == 1 t: CompletedTrade = store.completed_trades.trades[0] assert t.type == 'long' assert t.stop_loss_at == 1.0 assert t.entry_price == (1.1 + 1.11) / 2 assert t.exit_price == (1.2 + 1.3) / 2 assert t.take_profit_at == (1.2 + 1.3) / 2
def test_on_reduced_position(): set_up([ (exchanges.SANDBOX, 'BTC-USDT', timeframes.MINUTE_1, 'Test18'), ]) backtest_mode.run('2019-04-01', '2019-04-02', get_btc_candles()) assert len(store.completed_trades.trades) == 1 t1: CompletedTrade = store.completed_trades.trades[0] assert t1.type == 'long' assert t1.entry_price == 7 assert t1.exit_price == 13 assert t1.take_profit_at == 13 assert t1.stop_loss_at == 5 assert t1.qty == 2 assert t1.fee == 0