def test_decimals(self): # Long with decimals a = exchange.Account(2) a.enter_position('Long', 1, 0.00000001) self.assertEqual(a.total_value(0.00000002), 3) a.close_position(a.positions[0], 1, 0.00000002) self.assertEqual(a.buying_power, 3) # Short with decimals a = exchange.Account(2) a.enter_position('Short', 1, 0.00000002) self.assertEqual(a.total_value(0.00000001), 2.5) a.close_position(a.positions[0], 1, 0.00000001) self.assertEqual(a.buying_power, 2.5)
def run(self, data, **kwargs): """ Main method to start backtest :param data :: history data with ticks or bars :param logic: :param trading_interval: :param lookback_period: :return: """ self.account = exchange.Account( self.sim_params.get('capital_base', 10e5), fee=self.sim_params.get('fee', None) ) self.records = [] self.initialize() # TODO Add filter between start & end session from sim_params # resample data frame to 'D' by default self.data = resample(data, self.sim_params.get('data_frequency', 'D')) # start cycle for index, tick in self.data.iterrows(): # Update account variables self.account.date = index # update total value in account # TODO Replace by pandas DataFrame self.account.equity.append( (index, self.account.total_value(tick['close']))) # Execute trading logic lookback_data = self.data.loc[:index] try: self.logic(lookback_data) self.account.check_orders(tick) except Exception as ex: logger.exception(ex) raise ex # Cleanup empty positions self.account.purge_positions() self.performance = self.prepare_performance() self.results() self.analyze(**kwargs) return self.performance
def test_errors(self): a = exchange.Account(1000) self.assertRaises(ValueError, a.enter_position, 'Long', 2000, 10) self.assertRaises(ValueError, a.enter_position, 'Long', -500, 10) self.assertRaises(ValueError, a.enter_position, 'Long', 500, -10) # Enter valid position a.enter_position('Long', 250, 10) a.enter_position('Short', 250, 10) long = a.positions[0] short = a.positions[1] self.assertRaises(ValueError, a.close_position, long, 0.5, -20) self.assertRaises(ValueError, a.close_position, long, 1.01, 20) self.assertRaises(ValueError, a.close_position, long, -0.5, 20) self.assertRaises(ValueError, a.close_position, short, 1.01, 20) self.assertRaises(ValueError, a.close_position, short, -0.5, 20)
def test_both(self): a = exchange.Account(1000) a.enter_position('Long', 200, 20) # 10 a.enter_position('Short', 250, 25) # 10 self.assertEqual(a.buying_power, 550) self.assertEqual(a.total_value(25), 1050) long = a.positions[0] short = a.positions[1] a.close_position(long, 0.5, 40) # 5 a.close_position(short, 0.5, 12.5) # 5 self.assertEqual(a.buying_power, 937.5) self.assertEqual(a.total_value(12.5), 1187.5) a.close_position(long, 1.0, 50) a.close_position(short, 1.0, 50) self.assertEqual(a.buying_power, 1187.5) self.assertEqual(a.total_value(100), 1187.5)
def test_errors(self): a = exchange.Account(1000) with pytest.raises(ValueError): a.enter_position('Long', -500, 10) a.enter_position('Long', 500, -10) a.enter_position('Long', 2000, 10) # Enter valid position a.enter_position('Long', 250, 10) a.enter_position('Short', 250, 10) long = a.positions[0] short = a.positions[1] with pytest.raises(ValueError): a.close_position(long, 0.5, -20) a.close_position(long, 1.01, -20) a.close_position(long, -0.5, 20) a.close_position(short, 0.5, -20) a.close_position(short, -0.5, 20)
def test_short(self): a = exchange.Account(1000) # Win on a short a.enter_position('Short', 500, 10) a.enter_position('Short', 500, 10) self.assertEqual(a.buying_power, 0) self.assertEqual(a.total_value(10), 1000) S0 = a.positions[0] S1 = a.positions[1] a.close_position(S0, 0.5, 5) a.close_position(S1, 0.5, 5) self.assertEqual(a.buying_power, 750) self.assertEqual(a.total_value(5), 1500) a.close_position(S0, 0.5, 2.5) a.close_position(S1, 0.5, 2.5) self.assertEqual(a.buying_power, 1187.5) self.assertEqual(a.total_value(2.5), 1625) # Lose on a short a.enter_position('Short', 1000, 2) S2 = a.positions[2] a.close_position(S2, 0.5, 4) self.assertEqual(a.buying_power, 187.5) self.assertEqual(a.total_value(4), 587.5)
def test_long(self): a = exchange.Account(1000) # Win on a long a.enter_position('Long', 500, 10) a.enter_position('Long', 500, 10) self.assertEqual(a.buying_power, 0) self.assertEqual(a.total_value(10), 1000) L0 = a.positions[0] L1 = a.positions[1] a.close_position(L0, 0.5, 20) a.close_position(L1, 0.5, 20) self.assertEqual(a.buying_power, 1000) self.assertEqual(a.total_value(20), 2000) a.close_position(L0, 0.5, 40) a.close_position(L1, 0.5, 40) self.assertEqual(a.buying_power, 2000) self.assertEqual(a.total_value(40), 3000) # Lose on a long a.enter_position('Long', 1000, 50) L2 = a.positions[2] a.close_position(L2, 0.5, 25) self.assertEqual(a.buying_power, 1250) self.assertEqual(a.total_value(25), 2125)