def test_slice_opts_default(self): ctx = deepcopy(self.context_nocosts) ctx['strategy']['opt_params'] = [ # OptParam(name, default_value, min_value, max_value, step) OptParamArray('Direction', [1, -1]), OptParamArray('Opt2', [3, 5]), ] s = StrategyBase(ctx) res = s.slice_opts() res_required = [(1, 3), (1, 5), (-1, 3), (-1, 5)] self.assertEqual(len(list(res)), len(res_required)) for i in res: for j in res_required: self.assertEqual(i, j)
def test_slice_opts_preset(self): ctx = deepcopy(self.context_nocosts) ctx['strategy']['opt_params'] = [ # OptParam(name, default_value, min_value, max_value, step) OptParamArray('Direction', [1, -1]), OptParamArray('Opt2', [3, 5]), ] ctx['strategy']['opt_preset'] = [ # OptParam(name, default_value, min_value, max_value, step) (1, 5), (-1, 3) ] s = StrategyBase(ctx) res = s.slice_opts() res_required = [(1, 5), (-1, 3)] self.assertEqual(res, res_required)
def test_laststate_update_recalculated_exo_price(self): STRATEGY_CONTEXT = { 'strategy': { 'class': StrategyMACrossTrail, 'exo_name': './mat/strategy_270225.mat', 'direction': -1, 'opt_params': [ # OptParam(name, default_value, min_value, max_value, step) OptParamArray('Direction', [-1]), OptParam('SlowMAPeriod', 20, 10, 40, 5), OptParam('FastMAPeriod', 2, 5, 20, 5), OptParam('MedianPeriod', 5, 2, 10, 1) ], }, 'swarm': { 'members_count': 3, 'ranking_class': RankerHighestReturns(return_period=1), 'rebalance_time_function': SwarmRebalance.every_friday }, } swm_full = Swarm(STRATEGY_CONTEXT) swm_full.run_swarm() swm_full.pick() swm_start = Swarm(STRATEGY_CONTEXT) swm_start.strategy.data.at[pd.Timestamp('2016-03-04'), 'exo'] += 10 swm_start.strategy.data = swm_start.strategy.data.ix[:'2016-03-04'] swm_start.run_swarm() swm_start.pick() ctx = deepcopy(STRATEGY_CONTEXT) ctx['strategy']['opt_preset'] = Swarm._parse_params(swm_start.last_members_list) swm_next = Swarm(ctx) swm_next.strategy.data = swm_next.strategy.data.ix[:'2016-03-11'] swm_next.run_swarm() # Make sure that old EXO price used self.assertEqual(-2, swm_start.last_exposure) self.assertEqual(swm_full.picked_equity.ix['2016-03-04'], swm_start.picked_equity.ix['2016-03-04'] - 10*swm_start.last_exposure) # After this run swm_start._laststate_update(swm_next.strategy.data, swm_next.raw_exposure.sum(axis=1)) self.assertEqual(swm_full.picked_equity.ix['2016-03-04'], swm_start.picked_equity.ix['2016-03-04']) self.assertAlmostEqual(swm_full.picked_equity.ix['2016-03-07'], swm_start.picked_equity.ix['2016-03-07']) self.assertAlmostEqual(swm_full.picked_equity.ix['2016-03-10'], swm_start.picked_equity.ix['2016-03-10']) self.assertAlmostEqual(swm_full.picked_equity.ix['2016-03-11'], swm_start.picked_equity.ix['2016-03-11']) self.assertEqual(-3, swm_start.last_exposure)
def setUp(self): self.context_nocosts = { 'strategy': { 'class': StrategyBase, 'exo_name': 'strategy_270225', 'opt_params': [ # OptParam(name, default_value, min_value, max_value, step) OptParamArray('Direction', [1]), OptParam('SlowMAPeriod', 20, 10, 70, 10), OptParam('FastMAPeriod', 2, 5, 20, 5), OptParam('MedianPeriod', 5, 2, 20, 4) ], }, } self.context_withcosts = { 'strategy': { 'class': StrategyBase, 'exo_name': 'strategy_270225', 'opt_params': [ # OptParam(name, default_value, min_value, max_value, step) OptParamArray('Direction', [1]), OptParam('SlowMAPeriod', 20, 10, 70, 10), OptParam('FastMAPeriod', 2, 5, 20, 5), OptParam('MedianPeriod', 5, 2, 20, 4) ], }, 'costs': { 'manager': CostsManagerEXOFixed, 'context': { 'costs_options': 3.0, 'costs_futures': 3.0, } } }
def test_laststate_update_real_high_level(self): STRATEGY_CONTEXT = { 'strategy': { 'class': StrategyMACrossTrail, 'exo_name': './strategy_270225.mat', 'direction': -1, 'opt_params': [ # OptParam(name, default_value, min_value, max_value, step) OptParamArray('Direction', [-1]), OptParam('SlowMAPeriod', 20, 10, 40, 5), OptParam('FastMAPeriod', 2, 5, 20, 5), OptParam('MedianPeriod', 5, 2, 10, 1) ], }, 'swarm': { 'members_count': 3, 'ranking_class': RankerHighestReturns(return_period=1), 'rebalance_time_function': SwarmRebalance.every_friday } } swm_start = Swarm(STRATEGY_CONTEXT) swm_start.strategy.data = swm_start.strategy.data.ix[:'2016-03-04'] swm_start.run_swarm() swm_start.pick() self.assertEqual(19165.0, swm_start.picked_equity.ix['2016-03-04']) self.assertEqual(-2, swm_start.last_exposure) swarm_dict = swm_start.laststate_to_dict() # Loading and updating swarm online swm_start = Swarm.laststate_from_dict(swarm_dict, STRATEGY_CONTEXT) swm_start.update() self.assertEqual(19165.0, swm_start.picked_equity.ix['2016-03-04']) self.assertAlmostEqual(19335.0, swm_start.picked_equity.ix['2016-03-07']) self.assertAlmostEqual(18990.0, swm_start.picked_equity.ix['2016-03-10']) self.assertAlmostEqual(20235.0, swm_start.picked_equity.ix['2016-03-11'])
def setUp(self): self.STRATEGY_CONTEXT = { 'strategy': { 'class': StrategyMACrossTrail, 'exo_name': './mat/strategy_270225.mat', 'direction': -1, 'opt_params': [ # OptParam(name, default_value, min_value, max_value, step) OptParamArray('Direction', [-1]), OptParam('SlowMAPeriod', 20, 10, 40, 5), OptParam('FastMAPeriod', 2, 5, 20, 5), OptParam('MedianPeriod', 5, 2, 10, 1) ], }, 'swarm': { 'members_count': 1, 'ranking_class': RankerHighestReturns(return_period=1), 'rebalance_time_function': self.reblance_every_5th } }
def test_get_direction(self): ctx = { 'strategy': { 'direction': -1, 'opt_params': [ OptParamArray('Direction', [-1]), ], }, } with patch('warnings.warn') as mock_warn: Swarm.get_direction(ctx) self.assertTrue(mock_warn.called) ctx = { 'strategy': { 'opt_params': [ OptParamArray('Direction', [-1]), ], }, } self.assertEqual((-1, 'Short'), Swarm.get_direction(ctx)) ctx = { 'strategy': { 'opt_params': [ OptParamArray('Direction', [1]), ], }, } self.assertEqual((1, 'Long'), Swarm.get_direction(ctx)) ctx = { 'strategy': { 'opt_params': [ OptParamArray('Direction', [1, -1]), ], }, } self.assertEqual((0, 'Bidir'), Swarm.get_direction(ctx)) ctx = { 'strategy': { 'opt_params': [ OptParamArray('AnotherOptParam', [1, -1]), ], }, } self.assertRaises(ValueError, Swarm.get_direction, ctx) ctx = { 'strategy': { 'opt_params': [ OptParamArray('Direction', [1, -1, 1]), ], }, } self.assertRaises(ValueError, Swarm.get_direction, ctx) ctx = { 'strategy': { 'opt_params': [ OptParamArray('Direction', [2]), ], }, } self.assertRaises(ValueError, Swarm.get_direction, ctx)
from backtester.swarms.rebalancing import SwarmRebalance from strategies.strategy_bbands import StrategyBollingerBands STRATEGY_NAME = StrategyBollingerBands.name STRATEGY_SUFFIX = 'bullish-' STRATEGY_CONTEXT = { 'strategy': { 'class': StrategyBollingerBands, 'exo_name': 'ZC_CallSpread', # <---- Select and paste EXO name from cell above 'opt_params': [ #OptParam(name, default_value, min_value, max_value, step) OptParamArray('Direction', [1]), OptParam('BB_Period', 20, 5, 30, 10), OptParam('BB_K', 2, 7, 9, 1), ### Trend 0:5 #OptParamArray('RulesIndex', np.arange(26)[0:5]), ### Vola breakout 5:10 OptParamArray('RulesIndex', np.arange(26)[5:10]), ### High vola(BBands width percent rank > 80-90) 10:15 #OptParamArray('RulesIndex', np.arange(26)[10:15]), ### %B rules 15:26 #OptParamArray('RulesIndex', np.arange(26)[15:26]),
from backtester.swarms.rebalancing import SwarmRebalance from strategies.strategy_ichimokucloud import StrategyIchimokuCloud STRATEGY_NAME = StrategyIchimokuCloud.name STRATEGY_SUFFIX = 'bullish-' STRATEGY_CONTEXT = { 'strategy': { 'class': StrategyIchimokuCloud, 'exo_name': 'NG_PutSpread', # <---- Select and paste EXO name from cell above 'opt_params': [ #OptParam(name, default_value, min_value, max_value, step) OptParamArray('Direction', [1]), OptParam('conversion_line_period', 9, 3, 3, 19), OptParam('base_line_period', 26, 39, 39, 13), OptParam('leading_spans_lookahead_period', 26, 26, 26, 1), OptParam('leading_span_b_period', 52, 10, 10, 10), #OptParamArray('RulesIndex', np.arange(14)), OptParamArray('RulesIndex', [4]), #OptParamArray('RulesIndex', [7,8,9,10]), #OptParamArray('RulesIndex', [10,11,12,13]), OptParam('MedianPeriod', 5, 10, 10, 13) ], }, 'swarm': { 'members_count': 2, 'ranking_class': RankerBestWithCorrel(window_size=-1, correl_threshold=0.5),
from backtester.swarms.rebalancing import SwarmRebalance from strategies.strategy_bbands import StrategyBollingerBands STRATEGY_NAME = StrategyBollingerBands.name STRATEGY_SUFFIX = 'bullish-' STRATEGY_CONTEXT = { 'strategy': { 'class': StrategyBollingerBands, 'exo_name': 'ES_PutSpread', # <---- Select and paste EXO name from cell above 'opt_params': [ #OptParam(name, default_value, min_value, max_value, step) OptParamArray('Direction', [-1]), OptParam('BB_Period', 20, 30, 40, 5), OptParam('BB_K', 2, 7, 9, 1), ### Trend 0:5 #OptParamArray('RulesIndex', np.arange(26)[0:5]), ### Vola breakout 5:10 #OptParamArray('RulesIndex', np.arange(26)[5:10]), ### High vola(BBands width percent rank > 80-90) 10:15 OptParamArray('RulesIndex', np.arange(26)[10:15]), ### %B rules 15:26 #OptParamArray('RulesIndex', np.arange(26)[15:26]),
def test_laststate_update_handle_if_swarm_composition_is_empty_after_rebalance_with_costs(self, mock_get_costs): STRATEGY_CONTEXT = { 'strategy': { 'class': StrategyMACrossTrail, 'exo_name': './mat/strategy_270225.mat', 'direction': -1, 'opt_params': [ # OptParam(name, default_value, min_value, max_value, step) OptParamArray('Direction', [-1]), OptParam('SlowMAPeriod', 20, 10, 40, 5), OptParam('FastMAPeriod', 2, 5, 20, 5), OptParam('MedianPeriod', 5, 2, 10, 1) ], }, 'swarm': { 'members_count': 3, 'ranking_class': RankerHighestReturns(return_period=1), 'rebalance_time_function': SwarmRebalance.every_friday }, } # # Mocking the CostsManagerEXOFixed.get_costs # from backtester.matlab import loaddata exo_df, info = loaddata('./mat/strategy_270225.mat') mock_get_costs.return_value = pd.DataFrame({'rollover_costs': np.zeros(len(exo_df.index)), 'transaction_costs': np.ones(len(exo_df.index)) * 10}, index=exo_df.index) swm_full = Swarm(STRATEGY_CONTEXT) swm_full.strategy.data.at[pd.Timestamp('2016-03-04'), 'exo'] = swm_full.strategy.data.ix['2016-03-03']['exo'] swm_full.strategy.data.loc[:, 'delta'] = 1.0 swm_full.run_swarm() swm_full.pick() swm_start = Swarm(STRATEGY_CONTEXT) swm_start.strategy.data.at[pd.Timestamp('2016-03-04'), 'exo'] = swm_full.strategy.data.ix['2016-03-03']['exo'] swm_start.strategy.data = swm_start.strategy.data.ix[:'2016-03-04'] swm_start.strategy.data.loc[:, 'delta'] = 1.0 swm_start.run_swarm() swm_start.pick() ctx = deepcopy(STRATEGY_CONTEXT) ctx['strategy']['opt_preset'] = Swarm._parse_params(swm_start.last_members_list) swm_next = Swarm(ctx) swm_next.strategy.data.at[pd.Timestamp('2016-03-04'), 'exo'] = swm_full.strategy.data.ix['2016-03-03']['exo'] swm_next.strategy.data = swm_next.strategy.data.ix[:'2016-03-11'] swm_next.strategy.data.loc[:, 'delta'] = 1.0 swm_next.run_swarm() # Make sure that old EXO price used self.assertEqual(-2, swm_start.last_exposure) self.assertEqual(swm_full.picked_equity.ix['2016-03-03'], swm_start.picked_equity.ix['2016-03-04']) # After this run with patch('warnings.warn') as mock_warn: swm_start._laststate_update(swm_next.strategy.data, swm_next.raw_exposure.sum(axis=1), swm_next.strategy.costs) self.assertTrue(mock_warn.called) dt = '2016-03-04' self.assertEqual(swm_full.series['equity'].ix[dt], swm_start.series['equity'].ix[dt]) self.assertEqual(swm_full.series['exposure'].ix[dt], swm_start.series['exposure'].ix[dt]) self.assertEqual(swm_full.series['costs'].ix[dt], swm_start.series['costs'].ix[dt]) self.assertEqual(swm_full.series['delta'].ix[dt], swm_start.series['delta'].ix[dt]) dt = '2016-03-07' self.assertEqual(swm_full.series['equity'].ix[dt], swm_start.series['equity'].ix[dt]) self.assertEqual(swm_full.series['exposure'].ix[dt], swm_start.series['exposure'].ix[dt]) self.assertEqual(swm_full.series['costs'].ix[dt], swm_start.series['costs'].ix[dt]) self.assertEqual(swm_full.series['delta'].ix[dt], swm_start.series['delta'].ix[dt]) dt = '2016-03-08' self.assertEqual(swm_full.series['equity'].ix[dt], swm_start.series['equity'].ix[dt]) self.assertEqual(swm_full.series['exposure'].ix[dt], swm_start.series['exposure'].ix[dt]) self.assertEqual(swm_full.series['costs'].ix[dt], swm_start.series['costs'].ix[dt]) self.assertEqual(swm_full.series['delta'].ix[dt], swm_start.series['delta'].ix[dt]) dt = '2016-03-09' self.assertEqual(swm_full.series['equity'].ix[dt], swm_start.series['equity'].ix[dt]) self.assertEqual(swm_full.series['exposure'].ix[dt], swm_start.series['exposure'].ix[dt]) self.assertEqual(swm_full.series['costs'].ix[dt], swm_start.series['costs'].ix[dt]) self.assertEqual(swm_full.series['delta'].ix[dt], swm_start.series['delta'].ix[dt]) dt = '2016-03-10' self.assertEqual(swm_full.series['equity'].ix[dt], swm_start.series['equity'].ix[dt]) self.assertEqual(swm_full.series['exposure'].ix[dt], swm_start.series['exposure'].ix[dt]) self.assertEqual(swm_full.series['costs'].ix[dt], swm_start.series['costs'].ix[dt]) self.assertEqual(swm_full.series['delta'].ix[dt], swm_start.series['delta'].ix[dt]) dt = '2016-03-11' self.assertEqual(swm_full.series['equity'].ix[dt], swm_start.series['equity'].ix[dt]) self.assertEqual(swm_full.series['exposure'].ix[dt], swm_start.series['exposure'].ix[dt]) self.assertEqual(swm_full.series['costs'].ix[dt], swm_start.series['costs'].ix[dt]) self.assertEqual(swm_full.series['delta'].ix[dt], swm_start.series['delta'].ix[dt])
def test_laststate_update_real_with_costs(self, mock_get_costs): from backtester.matlab import loaddata STRATEGY_CONTEXT = { 'strategy': { 'class': StrategyMACrossTrail, 'exo_name': './mat/strategy_270225.mat', 'direction': -1, 'opt_params': [ # OptParam(name, default_value, min_value, max_value, step) OptParamArray('Direction', [-1]), OptParam('SlowMAPeriod', 20, 10, 40, 5), OptParam('FastMAPeriod', 2, 5, 20, 5), OptParam('MedianPeriod', 5, 2, 10, 1) ], }, 'swarm': { 'members_count': 3, 'ranking_class': RankerHighestReturns(return_period=1), 'rebalance_time_function': SwarmRebalance.every_friday }, 'costs': { 'manager': CostsManagerEXOFixed, 'context': { 'costs_options': 3.0, 'costs_futures': 3.0, } } } # # Mocking the CostsManagerEXOFixed.get_costs # exo_df, info = loaddata('./mat/strategy_270225.mat') mock_get_costs.return_value = pd.DataFrame({'rollover_costs': np.zeros(len(exo_df.index)), 'transaction_costs': np.ones(len(exo_df.index)) * 10}, index=exo_df.index) swm_full = Swarm(STRATEGY_CONTEXT) swm_full.strategy.data.loc[:, 'delta'] = 1.0 swm_full.run_swarm() swm_full.pick() swm_start = Swarm(STRATEGY_CONTEXT) swm_start.strategy.data = swm_start.strategy.data.ix[:'2016-03-18'] swm_start.strategy.data.loc[:, 'delta'] = 1.0 swm_start.run_swarm() swm_start.pick() ctx = deepcopy(STRATEGY_CONTEXT) ctx['strategy']['opt_preset'] = Swarm._parse_params(swm_start.last_members_list) swm_next = Swarm(ctx) swm_next.strategy.data = swm_next.strategy.data.ix[:'2016-03-25'] swm_next.strategy.data.loc[:, 'delta'] = 1.0 swm_next.run_swarm() dt = '2016-03-18' self.assertEqual(swm_full.series['equity'].ix[dt], swm_start.series['equity'].ix[dt]) self.assertEqual(swm_full.series['exposure'].ix[dt], swm_start.series['exposure'].ix[dt]) self.assertEqual(swm_full.series['costs'].ix[dt], swm_start.series['costs'].ix[dt]) self.assertEqual(np.isnan(swm_full.series['delta'].ix[dt]), np.isnan(swm_start.series['delta'].ix[dt])) self.assertEqual(swm_start.last_exposure, swm_full.picked_exposure.sum(axis=1).ix['2016-03-18']) # Updating swm_start (assuming that it was loaded from DB) swm_start._laststate_update(swm_next.strategy.data, swm_next.raw_exposure.sum(axis=1), swm_next.strategy.costs) dt = '2016-03-21' self.assertEqual(swm_full.series['equity'].ix[dt], swm_start.series['equity'].ix[dt]) self.assertEqual(swm_full.series['exposure'].ix[dt], swm_start.series['exposure'].ix[dt]) self.assertEqual(swm_full.series['costs'].ix[dt], swm_start.series['costs'].ix[dt]) self.assertEqual(swm_full.series['delta'].ix[dt], swm_start.series['delta'].ix[dt]) dt = '2016-03-22' self.assertEqual(swm_full.series['equity'].ix[dt], swm_start.series['equity'].ix[dt]) self.assertEqual(swm_full.series['exposure'].ix[dt], swm_start.series['exposure'].ix[dt]) self.assertEqual(swm_full.series['costs'].ix[dt], swm_start.series['costs'].ix[dt]) self.assertEqual(swm_full.series['delta'].ix[dt], swm_start.series['delta'].ix[dt]) dt = '2016-03-23' self.assertEqual(swm_full.series['equity'].ix[dt], swm_start.series['equity'].ix[dt]) self.assertEqual(swm_full.series['exposure'].ix[dt], swm_start.series['exposure'].ix[dt]) self.assertEqual(swm_full.series['costs'].ix[dt], swm_start.series['costs'].ix[dt]) self.assertEqual(swm_full.series['delta'].ix[dt], swm_start.series['delta'].ix[dt]) dt = '2016-03-24' self.assertEqual(swm_full.series['equity'].ix[dt], swm_start.series['equity'].ix[dt]) self.assertEqual(swm_full.series['exposure'].ix[dt], swm_start.series['exposure'].ix[dt]) self.assertEqual(swm_full.series['costs'].ix[dt], swm_start.series['costs'].ix[dt]) self.assertEqual(swm_full.series['delta'].ix[dt], swm_start.series['delta'].ix[dt]) dt = '2016-03-25' self.assertEqual(swm_full.series['equity'].ix[dt], swm_start.series['equity'].ix[dt]) self.assertEqual(swm_full.series['exposure'].ix[dt], swm_start.series['exposure'].ix[dt]) self.assertEqual(swm_full.series['costs'].ix[dt], swm_start.series['costs'].ix[dt]) self.assertEqual(swm_full.series['delta'].ix[dt], swm_start.series['delta'].ix[dt])
def test_pick_equity_calculation(self): def reblance_every_5th(swarm): return pd.Series(swarm.index % 5 == 0, index=swarm.index) STRATEGY_CONTEXT = { 'strategy': { 'class': StrategyMACrossTrail, 'exo_name': './strategy_270225.mat', 'direction': -1, 'opt_params': [ # OptParam(name, default_value, min_value, max_value, step) OptParamArray('Direction', [-1]), OptParam('SlowMAPeriod', 20, 10, 40, 5), OptParam('FastMAPeriod', 2, 5, 20, 5), OptParam('MedianPeriod', 5, 2, 10, 1) ], }, 'swarm': { 'members_count': 1, 'ranking_class': RankerHighestReturns(return_period=1), 'rebalance_time_function': reblance_every_5th } } swm_index = np.array(range(20)) swm_values = np.array([ [ 0., 0.], # 0 [ 1., -1.], [ 2., -2.], [ 3., -3.], [ 4., -4.], [ 5., -5.], # 5 [ 6., -6.], [ 7., -7.], [ 8., -8.], [ 9., -9.], [ 6., -6.], # 10 [ 5., -5.], [ 4., -4.], [ 3., -3.], [ 2., -2.], [ 1., -1.], #15 [ 0., 0.], [ -1., 1.], [ -2., 2.], [ -3., 3.]]) exo_price = np.array([ 0, 1, 2, 3, 4, 5, # 5 6, 7, 8, 9, 6, # 10 5, 4, 3, 2, 1, 0, -1, -2, -3 ]) exposure_values = np.array([ [1., -1.], # 0 [1., -1.], [1., -1.], [1., -1.], [1., -1.], [1., -1.], # 5 [1., -1.], [1., -1.], [1., -1.], [1., -1.], [1., -1.], # 10 [1., -1.], [1., -1.], [1., -1.], [1., -1.], [1., -1.], [1., -1.], [1., -1.], [1., -1.], [1., -1.], ]) swm = Swarm(STRATEGY_CONTEXT) swm._swarm = pd.DataFrame(swm_values, swm_index) swm._swarm_inposition = pd.DataFrame(np.ones((20, 2)), swm_index) swm._swarm_exposure = pd.DataFrame(exposure_values, swm_index, dtype=np.float) swm.strategy.data = pd.DataFrame({'exo': pd.Series(exo_price, index=swm_index, dtype=np.float)}) swm.strategy.costs = None swm_res = np.array([ [ 0.], #0 - ignored by default [ 0.], [ 0.], [ 0.], [ 0.], [ 0.], #5 - first rebalance (pick system #0) [ 0.], # Apply delayed rebalance we checked rebalance on #5 but change the position at #6 [ 1.], [ 2.], [ 3.], [ 0.], #10 - pick another systems (but keep prev system change to next day) [ -1.], # Apply delayed rebalance we checked rebalance on #10 but change the position at #11 [ 0.], [ 1.], [ 2.], [ 3.], #15 - keep system #1 [ 4.], [ 5.], [ 6.], [ 7.]] ) expected = pd.DataFrame(swm_res, index=swm_index) swm.pick() for k, v in expected[0].items(): print(k) self.assertEqual(k, swm.picked_swarm.index[k]) self.assertEqual(v, swm.picked_swarm[0][k])
def test_laststate_update(self): def reblance_every_5th(swarm): return pd.Series(swarm.index % 5 == 0, index=swarm.index) STRATEGY_CONTEXT = { 'strategy': { 'class': StrategyMACrossTrail, 'exo_name': './mat/strategy_270225.mat', 'direction': -1, 'opt_params': [ # OptParam(name, default_value, min_value, max_value, step) OptParamArray('Direction', [-1]), OptParam('SlowMAPeriod', 20, 10, 40, 5), OptParam('FastMAPeriod', 2, 5, 20, 5), OptParam('MedianPeriod', 5, 2, 10, 1) ], }, 'swarm': { 'members_count': 1, 'ranking_class': RankerHighestReturns(return_period=1), 'rebalance_time_function': reblance_every_5th } } swm_index = np.array(range(11)) swm_values = np.array([ [ 0., 0.], # 0 [ 1., -1.], [ 2., -2.], [ 3., -3.], [ 4., -4.], [ 5., -5.], # 5 [ 6., -6.], [ 7., -7.], [ 8., -8.], [ 9., -9.], [ 6., -6.], # 10 ]) exo_price = np.array([ 0, 1, 2, 3, 4, 5, # 5 6, 7, 8, 9, 6 # 10 ]) exposure_values = np.array([ [1., -1.], # 0 [1., -1.], [1., -1.], [1., -1.], [1., -1.], [1., -1.], # 5 [1., -1.], [1., -1.], [1., -1.], [1., -1.], [1., -1.], # 10 ]) swm = Swarm(STRATEGY_CONTEXT) swm._swarm = pd.DataFrame(swm_values, swm_index) swm._swarm_inposition = pd.DataFrame(np.ones((11, 2)), swm_index) swm._swarm_exposure = pd.DataFrame(exposure_values, swm_index, dtype=np.float) swm.strategy.data = pd.DataFrame({'exo': pd.Series(exo_price, index=swm_index, dtype=np.float)}) swm.strategy.costs = None swm_res = np.array([ 0., #0 - ignored by default 0., 0., 0., 0., 0., #5 - first rebalance (pick system #0) 0., # Apply delayed rebalance we checked rebalance on #5 but change the position at #6 1., 2., 3., 0., #10 - pick another systems (but keep prev system change to next day) ]) expected = pd.DataFrame(swm_res, index=swm_index) swm.pick() self.assertEqual(2, len(swm.rebalance_info)) self.assertEqual(5, swm.rebalance_info[0]['rebalance_date']) self.assertEqual(10, swm.rebalance_info[1]['rebalance_date']) for k, v in expected[0].items(): #print(k) self.assertEqual(k, swm.picked_swarm.index[k]) self.assertEqual(v, swm.picked_swarm[0][k]) self.assertEqual(swm.last_date, 10) self.assertEqual(swm.last_rebalance_date, 10) self.assertEqual(swm.last_exposure, 1) self.assertEqual(swm.last_members_list, [1]) self.assertEqual(True, np.all(swm.picked_equity.values == expected[0].values)) # # DO swarm update with new quotes # swm_index = np.array(range(14)) exo_price = np.array([ 0., # 0 - ignored by default 0., 0., 0., 0., 0., # 5 - first rebalance (pick system #0) 0., # Apply delayed rebalance we checked rebalance on #5 but change the position at #6 1., 2., 3., 0., # 10 - pick another systems (but keep prev system change to next day) 10., # Should be added with last exposure 11., 13. ]) swarm_exposure = np.array([ 0., # 0 - ignored by default 0., 0., 0., 0., 0., # 5 - first rebalance (pick system #0) 0., 0., 0., 0., 0., # 10 2., # Should be added with last exposure 2., 2., ]) #swm = Swarm(STRATEGY_CONTEXT) # Little hack swm._last_exoquote = 0.0 # exo_price on #10 # Little hack swm._last_exposure = -1 self.assertEqual(swm.last_date, 10) self.assertEqual(swm.last_rebalance_date, 10) self.assertEqual(swm.last_exposure, -1) self.assertEqual(swm.last_exoquote, 0) self.assertEqual(swm.last_members_list, [1]) exo_df = pd.DataFrame({'exo': exo_price}, index=swm_index) swm._laststate_update(exo_df, pd.Series(swarm_exposure, index=swm_index)) self.assertEqual(swm.last_date, 13) self.assertEqual(swm.last_rebalance_date, 10) self.assertEqual(swm.last_exposure, 2) self.assertEqual(swm.last_exoquote, 13) self.assertEqual(swm.last_members_list, [1]) swm_res = np.array([ 0., # 0 - ignored by default 0., 0., 0., 0., 0., # 5 - first rebalance (pick system #0) 0., # Apply delayed rebalance we checked rebalance on #5 but change the position at #6 1., 2., 3., 0., # 10 - pick another systems (but keep prev system change to next day) -10., # Apply delayed rebalance we checked rebalance on #10 but change the position at #11 -8., -4., ]) expected = pd.Series(swm_res, index=swm_index) self.assertEqual(len(swm.picked_equity), len(expected)) for k, v in expected.items(): print(k) self.assertEqual(k, swm.picked_equity.index[k]) self.assertEqual(v, swm.picked_equity.values[k])
def test_rebalanceinformation_before_next_day(self): def riseup(swarm_slice, nsystems): result = [] rank_info = [] # Calculate 14-period equity returns and sort values last_diff = swarm_slice.diff(periods=1).iloc[-1, :].sort_values(ascending=False) # Pick best nsystems best = last_diff[:nsystems] for k, v in best.items(): if not np.isnan(v) and v > 0: result.append(k) rank_info.append({'rank_value': v}) return result, rank_info def reblance_every_5th(swarm): return pd.Series(swarm.index % 5 == 0, index=swarm.index) STRATEGY_CONTEXT = { 'strategy': { 'class': StrategyMACrossTrail, 'exo_name': 'strategy_270225', 'direction': -1, 'opt_params': [ # OptParam(name, default_value, min_value, max_value, step) OptParamArray('Direction', [-1]), OptParam('SlowMAPeriod', 20, 10, 40, 5), OptParam('FastMAPeriod', 2, 5, 20, 5), OptParam('MedianPeriod', 5, 2, 10, 1) ], }, 'swarm': { 'members_count': 1, 'ranking_class': RankerHighestReturns(return_period=1), 'rebalance_time_function': reblance_every_5th } } swm_index = np.array(range(11)) swm_values = np.array([ [ 0., 0.], # 0 [ 1., -1.], [ 2., -2.], [ 3., -3.], [ 4., -4.], [ 5., -5.], # 5 [ 6., -6.], [ 7., -7.], [ 8., -8.], [ 9., -9.], [ 6., -6.], # 10 ]) exposure_values = np.array([ [1., -1.], # 0 [1., -1.], [1., -1.], [1., -1.], [1., -1.], [1., -1.], # 5 [1., -1.], [1., -1.], [1., -1.], [1., -1.], [1., -1.], # 10 ]) exo_price = np.array([ 0, 1, 2, 3, 4, 5, # 5 6, 7, 8, 9, 6 #10 ]) swm = Swarm(STRATEGY_CONTEXT) swm._swarm = pd.DataFrame(swm_values, swm_index) swm._swarm_inposition = pd.DataFrame(np.ones((11, 2)), swm_index) swm._swarm_exposure = pd.DataFrame(exposure_values, swm_index, dtype=np.float) swm.strategy.data = pd.DataFrame({'exo': pd.Series(exo_price, index=swm_index, dtype=np.float)}) swm.strategy.costs = None #equity1, _st_pass = stats_exposure(swm.strategy.data['exo'], swm._swarm_exposure[1], costs=None) swm_res = np.array([ [ 0.], #0 - ignored by default [ 0.], [ 0.], [ 0.], [ 0.], [ 0.], #5 - first rebalance (pick system #0) [ 0.], # Apply delayed rebalance we checked rebalance on #5 but change the position at #6 [ 1.], [ 2.], [ 3.], [ 0.], #10 - pick another systems (but keep prev system change to next day) ]) expected = pd.DataFrame(swm_res, index=swm_index) swm.pick() self.assertEqual(2, len(swm.rebalance_info)) self.assertEqual(5, swm.rebalance_info[0]['rebalance_date']) self.assertEqual(10, swm.rebalance_info[1]['rebalance_date']) for k, v in expected[0].items(): print(k) self.assertEqual(k, swm.picked_swarm.index[k]) self.assertEqual(v, swm.picked_swarm[0][k])
from backtester.strategy import OptParam, OptParamArray from backtester.swarms.rankingclasses import * from backtester.swarms.rebalancing import SwarmRebalance from strategies.strategy_ichimokucloud import StrategyIchimokuCloud STRATEGY_NAME = StrategyIchimokuCloud.name STRATEGY_SUFFIX = 'bearish-' STRATEGY_CONTEXT = { 'strategy': { 'class': StrategyIchimokuCloud, 'exo_name': 'ES_PutSpread', # <---- Select and paste EXO name from cell above 'opt_params': [ #OptParam(name, default_value, min_value, max_value, step) OptParamArray('Direction', [1]), OptParam('conversion_line_period', 9, 5, 5, 1), OptParam('base_line_period', 26, 26, 26, 13), OptParam('leading_spans_lookahead_period', 26, 13, 13, 1), OptParam('leading_span_b_period', 52, 26, 26, 10), #OptParamArray('RulesIndex', np.arange(14)), #OptParamArray('RulesIndex', [4,5,7]), OptParamArray('RulesIndex', [10,11,12,13]), OptParam('MedianPeriod', 5, 20, 20, 10) ], }, 'swarm': { 'members_count': 2, 'ranking_class': RankerBestWithCorrel(window_size=-1, correl_threshold=0.5), 'rebalance_time_function': SwarmRebalance.every_friday, },
from backtester.swarms.rebalancing import SwarmRebalance from strategies.strategy_renko_no_exit_on_patterns import StrategyRenkoPatterns_no_exit_on_patterns STRATEGY_NAME = StrategyRenkoPatterns_no_exit_on_patterns.name STRATEGY_SUFFIX = 'bullish-' STRATEGY_CONTEXT = { 'strategy': { 'class': StrategyRenkoPatterns_no_exit_on_patterns, 'exo_name': 'CL_PutSpread', # <---- Select and paste EXO name from cell above 'opt_params': [ # OptParam(name, default_value, min_value, max_value, step) OptParamArray('Direction', [1]), OptParam('BoxSize', 500, 400, 500, 100), OptParam('MoveCount', 2, 3, 3, 1), OptParamArray('RulesIndex', np.arange(9)), OptParam('MedianPeriod', 5, 20, 20, 19) ], }, 'swarm': { 'members_count': 2, 'ranking_class': RankerBestWithCorrel(window_size=-1, correl_threshold=0.5), 'rebalance_time_function': SwarmRebalance.every_friday, }, 'costs': { 'manager': CostsManagerEXOFixed, 'context': {
def test_laststate_save_load(self): STRATEGY_CONTEXT = { 'strategy': { 'class': StrategyMACrossTrail, 'exo_name': './strategy_270225.mat', 'direction': -1, 'opt_params': [ # OptParam(name, default_value, min_value, max_value, step) OptParamArray('Direction', [-1]), OptParam('SlowMAPeriod', 20, 10, 40, 5), OptParam('FastMAPeriod', 2, 5, 20, 5), OptParam('MedianPeriod', 5, 2, 10, 1) ], }, 'swarm': { 'members_count': 3, 'ranking_class': RankerHighestReturns(return_period=1), 'rebalance_time_function': SwarmRebalance.every_friday } } swm = Swarm(STRATEGY_CONTEXT) swm.run_swarm() swm.pick() self.assertEqual(False, swm._islast_state) s = swm.laststate_to_dict() import pickle self.assertEqual(s['direction'], -1) self.assertEqual(s['alpha_name'], StrategyMACrossTrail.name) self.assertEqual(s['exo_name'], swm.exo_name ) self.assertEqual(s['swarm_name'], swm.name ) self.assertEqual(s['swarm_series'], pickle.dumps(swm._swarm_series)) self.assertEqual(s['last_rebalance_date'], swm.last_rebalance_date) self.assertEqual(s['last_members_list'], swm.last_members_list) self.assertEqual(s['last_exoquote'], swm.last_exoquote ) self.assertEqual(s['last_prev_exposure'], swm.last_prev_exposure) self.assertEqual(s['last_exposure'], swm.last_exposure) self.assertEqual(s['last_date'], swm.last_date) self.assertEqual(s['instrument'], swm.instrument) self.assertEqual(s['exo_type'], swm.exo_type) self.assertEqual(s['max_exposure'], swm.max_exposure) swm = Swarm.laststate_from_dict(s, STRATEGY_CONTEXT) self.assertEqual(True, swm._islast_state) self.assertEqual(swm.direction[0], -1) self.assertEqual(swm.strategy.name, StrategyMACrossTrail.name) self.assertEqual(s['exo_name'], swm.exo_name) self.assertEqual(s['swarm_name'], swm.name) self.assertEqual(s['last_rebalance_date'], swm.last_rebalance_date) self.assertEqual(s['last_members_list'], swm.last_members_list) self.assertEqual(s['last_exoquote'], swm.last_exoquote) self.assertEqual(s['last_prev_exposure'], swm.last_prev_exposure) self.assertEqual(s['last_exposure'], swm.last_exposure) self.assertEqual(s['last_date'], swm.last_date) self.assertEqual(s['instrument'], swm.instrument) self.assertEqual(s['exo_type'], swm.exo_type) self.assertEqual(s['max_exposure'], swm.max_exposure) eq = pickle.loads(s['swarm_series'])['equity'] self.assertEqual(True, np.all(eq == swm.picked_equity.values))
from backtester.swarms.rebalancing import SwarmRebalance from strategies.strategy_pnf import StrategyPointAndFigurePatterns STRATEGY_NAME = "PointAndFigure" STRATEGY_SUFFIX = 'smallbox-bearish-sample-' STRATEGY_CONTEXT = { 'strategy': { 'class': StrategyPointAndFigurePatterns, 'exo_name': 'CL_BearishCollarBW', # <---- Select and paste EXO name from cell above 'opt_params': [ # OptParam(name, default_value, min_value, max_value, step) OptParamArray('Direction', [1]), OptParam('BoxSize', 1, 30, 50, 10), OptParam('Reversal', 2, 15, 20, 1), OptParamArray('MaxMinWindowPercent', [0.05]), OptParam('ColumnConsecMoveCount', 2, 1, 1, 1), OptParamArray('RulesIndex', np.arange(9)), OptParam('MedianPeriod', 5, 30, 50, 10), ], }, 'swarm': { 'members_count': 2, 'ranking_class': RankerBestWithCorrel(window_size=-1, correl_threshold=0.5), 'rebalance_time_function': SwarmRebalance.every_friday, }, 'costs': {
from strategies.strategy_swingpoint import StrategySwingPoint STRATEGY_NAME = StrategySwingPoint.name STRATEGY_SUFFIX = 'bearish-' # TODO: check that Long direction on call spread is Bearish? STRATEGY_CONTEXT = { 'strategy': { 'class': StrategySwingPoint, 'exo_name': 'NG_CallSpread', # <---- Select and paste EXO name from cell above 'opt_params': [ #OptParam(name, default_value, min_value, max_value, step) OptParamArray('Direction', [1]), OptParam('sphTreshold', 2, 3, 12, 2), OptParam('splTreshold', 2, 3, 12, 2), #bearish_breakout, bearish_failure, bullish_breakout, bullish_failure OptParamArray('RulesIndex', [0, 1, 2, 3]), OptParam('MedianPeriod', 5, 40, 60, 10) ], }, 'swarm': { 'members_count': 2, 'ranking_class': RankerBestWithCorrel(window_size=-1, correl_threshold=0.5), 'rebalance_time_function': SwarmRebalance.every_friday, }, 'costs': { 'manager': CostsManagerEXOFixed,
from backtester.strategy import OptParam, OptParamArray from backtester.swarms.rankingclasses import * from backtester.swarms.rebalancing import SwarmRebalance from strategies.strategy_macross_with_trail import StrategyMACrossTrail STRATEGY_NAME = StrategyMACrossTrail.name STRATEGY_SUFFIX = 'bearish-' STRATEGY_CONTEXT = { 'strategy': { 'class': StrategyMACrossTrail, 'exo_name': 'ZC_PutSpread', # <---- Select and paste EXO name from cell above 'opt_params': [ #OptParam(name, default_value, min_value, max_value, step) OptParamArray('Direction', [1]), OptParam('SlowMAPeriod', 20, 10, 70, 5), OptParam('FastMAPeriod', 2, 5, 20, 5), OptParam('MedianPeriod', 5, 30, 30, 1) ], }, 'swarm': { 'members_count': 2, 'ranking_class': RankerBestWithCorrel(window_size=-1, correl_threshold=0.5), 'rebalance_time_function': SwarmRebalance.every_friday, }, 'costs': { 'manager': CostsManagerEXOFixed, 'context': { 'costs_options': 3.0, 'costs_futures': 3.0,
from backtester.swarms.rebalancing import SwarmRebalance from strategies.strategy_ichimokucloud import StrategyIchimokuCloud STRATEGY_NAME = StrategyIchimokuCloud.name STRATEGY_SUFFIX = 'bullish-' STRATEGY_CONTEXT = { 'strategy': { 'class': StrategyIchimokuCloud, 'exo_name': 'ZC_CallSpread', # <---- Select and paste EXO name from cell above 'opt_params': [ # OptParam(name, default_value, min_value, max_value, step) OptParamArray('Direction', [1]), OptParam('conversion_line_period', 9, 5, 5, 45), OptParam('base_line_period', 26, 26, 26, 1), OptParam('leading_spans_lookahead_period', 26, 13, 13, 1), OptParam('leading_span_b_period', 52, 52, 52, 10), # OptParamArray('RulesIndex', np.arange(14)), # OptParamArray('RulesIndex', [5]), OptParamArray('RulesIndex', [7, 8, 9, 10]), # OptParamArray('RulesIndex', [10,11,12,13]), # 7,9 OptParam('MedianPeriod', 5, 39, 39, 13) ], }, 'swarm': { 'members_count': 2, 'ranking_class': RankerBestWithCorrel(window_size=-1, correl_threshold=0.5),
from backtester.swarms.rebalancing import SwarmRebalance from strategies.strategy_swingpoint import StrategySwingPoint STRATEGY_NAME = "SwingPoint" STRATEGY_SUFFIX = 'bearish-sample-' STRATEGY_CONTEXT = { 'strategy': { 'class': StrategySwingPoint, 'exo_name': 'CL_BearishCollarBW', # <---- Select and paste EXO name from cell above 'opt_params': [ # OptParam(name, default_value, min_value, max_value, step) OptParamArray('Direction', [-1]), OptParam('sphTreshold', 2, 2, 2, 2), OptParam('splTreshold', 2, 2, 13, 2), # bearish_breakout, bearish_failure, bullish_breakout, bullish_failure OptParamArray('RulesIndex', [3]), OptParam('MedianPeriod', 5, 30, 30, 5) ], }, 'swarm': { 'members_count': 5, 'ranking_class': RankerBestWithCorrel(window_size=-1, correl_threshold=0.5), 'rebalance_time_function': SwarmRebalance.every_friday, }, 'costs': { 'manager': CostsManagerEXOFixed,
def main(args, loglevel): if args.logfile == '': logging.basicConfig( stream=sys.stdout, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=loglevel) else: logging.basicConfig( filename=args.logfile, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=loglevel) signalapp = SignalApp("AlphaRebalancer", APPCLASS_ALPHA, RABBIT_HOST, RABBIT_USER, RABBIT_PASSW) signalapp.send(MsgStatus('INIT', 'Initiating alpha rebalancer script')) #exo_names = get_exo_names_mat() logging.getLogger("pika").setLevel(logging.WARNING) logging.info("Starting...") exo_storage = EXOStorage(MONGO_CONNSTR, MONGO_EXO_DB) exo_names = exo_storage.exo_list() for exo in exo_names: logging.info("Processing EXO: " + exo) # Load alpha modules to process for module in os.listdir('alphas'): # # Custom EXO folder found # swm = None context = None if module.lower() == exo.lower() and os.path.isdir( os.path.join('alphas', module)): for custom_file in os.listdir(os.path.join('alphas', module)): if 'alpha_' in custom_file and '.py' in custom_file: logging.debug( 'Processing custom module: ' + os.path.join('alphas', module, custom_file)) try: m = importlib.import_module( 'scripts.alphas.{0}.{1}'.format( module, custom_file.replace('.py', ''))) context = m.STRATEGY_CONTEXT context['strategy']['exo_name'] = exo context['strategy'][ 'suffix'] = m.STRATEGY_SUFFIX + 'custom' context['strategy']['exo_storage'] = exo_storage logging.info( 'Running CUSTOM alpha: ' + Swarm.get_name( m.STRATEGY_CONTEXT, m.STRATEGY_SUFFIX)) if 'exo_name' in context['strategy'] and context[ 'strategy']['exo_name'] != exo: logging.error( "Custom strategy context exo_name != current EXO name (folder mismatch?)" ) raise ValueError( "Custom strategy context exo_name != current EXO name (folder mismatch?)" ) swm = Swarm(context) swm.run_swarm() swm.pick() # # Saving last EXO state to online DB # swmonline = SwarmOnlineManager( MONGO_CONNSTR, MONGO_EXO_DB, m.STRATEGY_CONTEXT) logging.debug('Saving: {0}'.format(swm.name)) swmonline.save(swm) except: logging.exception('Exception occurred:') signalapp.send( MsgStatus('ERROR', 'Exception in {0}'.format( Swarm.get_name( m.STRATEGY_CONTEXT, m.STRATEGY_SUFFIX)), notify=True)) elif 'alpha_' in module and '.py' in module: logging.debug('Processing generic module: ' + module) try: m = importlib.import_module('scripts.alphas.{0}'.format( module.replace('.py', ''))) for direction in [-1, 1]: context = m.STRATEGY_CONTEXT context['strategy']['exo_name'] = exo context['strategy']['opt_params'][0] = OptParamArray( 'Direction', [direction]) context['strategy']['suffix'] = m.STRATEGY_SUFFIX context['strategy']['exo_storage'] = exo_storage logging.info('Running alpha: ' + Swarm.get_name(m.STRATEGY_CONTEXT) + ' Direction: {0}'.format(direction)) swm = Swarm(context) swm.run_swarm() swm.pick() # # Saving last EXO state to online DB # swmonline = SwarmOnlineManager(MONGO_CONNSTR, MONGO_EXO_DB, m.STRATEGY_CONTEXT) logging.debug('Saving: {0}'.format(swm.name)) swmonline.save(swm) except: logging.exception('Exception occurred:') signalapp.send( MsgStatus('ERROR', 'Exception in {0}'.format( Swarm.get_name(m.STRATEGY_CONTEXT, m.STRATEGY_SUFFIX)), notify=True)) logging.info("Processing accounts positions") assetindex = AssetIndexMongo(MONGO_CONNSTR, MONGO_EXO_DB) datasource = DataSourceMongo(MONGO_CONNSTR, MONGO_EXO_DB, assetindex, futures_limit=10, options_limit=10, exostorage=exo_storage) exmgr = ExecutionManager(MONGO_CONNSTR, datasource, dbname=MONGO_EXO_DB) exmgr.account_positions_process(write_to_db=True) signalapp.send(MsgStatus('DONE', 'Alpha rebalancer script', notify=True)) logging.info("Done.")