def test_get_raw_fixed_forecast_weights(self): # fixed weights: # nested dict (in config) ans1a = self.system.combForecast.get_forecast_weights("EDOLLAR") self.assertAlmostEqual(ans1a.ewmac16.values[-1], 0.5) ans1b = self.system.combForecast.get_raw_forecast_weights("BUND") self.assertEqual(ans1b.ewmac8.values[-1], 1.0) # missing; equal weights config = copy.copy(self.config) del (config.forecast_weights) system2 = System( [self.rawdata, self.rules, self.fcs, self.forecast_combine()], self.data, config) ans2 = system2.combForecast.get_forecast_weights("BUND") self.assertAlmostEqual(ans2.ewmac8.values[-1], 0.49917057) # smoothing # non nested dict config.forecast_weights = dict(ewmac8=0.1, ewmac16=0.9) system3 = System( [self.rawdata, self.rules, self.fcs, self.forecast_combine()], self.data, config) ans3 = system3.combForecast.get_forecast_weights("BUND") self.assertEqual(ans3.ewmac8.values[-1], 0.099834114877206212)
def test_get_capped_forecast(self): # fixed, normal cap self.assertAlmostEqual( self.system.forecastScaleCap.get_capped_forecast( "EDOLLAR", "ewmac8").tail(1).values[0], 0.871230635) # estimated, normal cap config = copy.copy(self.config) config.use_forecast_scale_estimates = True system2 = System([self.rawdata, self.rules, self.forecast_scale_cap()], self.data, config) self.assertAlmostEqual(system2.forecastScaleCap.get_forecast_scalar( "EDOLLAR", "ewmac8").tail(1).values[0], 5.8, places=1) # binding cap config.use_forecast_scale_estimates = False config.forecast_cap = 0.2 system3 = System([self.rawdata, self.rules, self.forecast_scale_cap()], self.data, config) self.assertAlmostEqual( system3.forecastScaleCap.get_capped_forecast( "EDOLLAR", "ewmac8").tail(1).values[0], 0.2)
def testRules(self): # config=Config(dict(trading_rules=dict(ewmac=dict(function="pysystemtrade.systems.provided.example.rules.ewmac_forecast_with_defaults")))) data = csvFuturesData("sysdata.tests") rules = Rules( dict( function= "pysystemtrade.systems.provided.example.rules.ewmac_forecast_with_defaults" )) system = System([rules], data) ans = system.rules.get_raw_forecast("EDOLLAR", "rule0") self.assertAlmostEqual(ans.tail(1).values[0], 2.1384223788141838, 5) config = Config( dict(trading_rules=dict(ewmac=dict( function= "pysystemtrade.systems.provided.example.rules.ewmac_forecast_with_defaults" )))) rules = Rules() system = System([rules], data, config) ans = system.rules.get_raw_forecast("EDOLLAR", "ewmac") self.assertAlmostEqual(ans.tail(1).values[0], 2.1384223788141838, 5) config = Config( "pysystemtrade.systems.provided.example.exampleconfig.yaml") rawdata = RawData() rules = Rules() system = System([rules, rawdata], data, config) ans = system.rules.get_raw_forecast("EDOLLAR", "ewmac8") self.assertAlmostEqual(ans.tail(1).values[0], 0.16438313875, 5)
def test_get_trading_rule_list(self): # fixed weights ans = self.system.combForecast.get_trading_rule_list("EDOLLAR") self.assertEqual(ans, ['ewmac16', 'ewmac8']) ans2 = self.system.combForecast.get_trading_rule_list("BUND") self.assertEqual(ans2, ['ewmac8']) # fixed weights - non nested dict config = copy.copy(self.config) config.forecast_weights = dict(ewmac8=.5, ewmac16=.5) system2 = System( [self.rawdata, self.rules, self.fcs, self.forecast_combine()], self.data, config) ans3 = system2.combForecast.get_trading_rule_list("EDOLLAR") self.assertEqual(ans3, ['ewmac16', 'ewmac8']) ans4 = system2.combForecast.get_trading_rule_list("BUND") self.assertEqual(ans4, ans3) # fixed weights - missing del (config.forecast_weights) system3 = System( [self.rawdata, self.rules, self.fcs, self.forecast_combine()], self.data, config) ans5 = system3.combForecast.get_trading_rule_list("EDOLLAR") self.assertEqual(ans5, ['ewmac16', 'ewmac8']) # estimated weights - missing config.use_forecast_weight_estimates = True system4 = System( [self.rawdata, self.rules, self.fcs, self.forecast_combine()], self.data, config) ans6 = system4.combForecast.get_trading_rule_list("EDOLLAR") self.assertEqual(ans6, ['ewmac16', 'ewmac8']) # estimated weights - non nested setattr(config, "rule_variations", ["ewmac8"]) system5 = System( [self.rawdata, self.rules, self.fcs, self.forecast_combine()], self.data, config) ans6 = system5.combForecast.get_trading_rule_list("EDOLLAR") self.assertEqual(ans6, ['ewmac8']) #estimated weights - nested dict setattr( config, "rule_variations", dict(EDOLLAR=["ewmac8"], BUND=["ewmac16"], US10=["ewmac8", "ewmac16"])) system6 = System( [self.rawdata, self.rules, self.fcs, self.forecast_combine()], self.data, config) ans7 = system6.combForecast.get_trading_rule_list("EDOLLAR") self.assertEqual(ans7, ['ewmac8']) ans8 = system6.combForecast.get_trading_rule_list("BUND") self.assertEqual(ans8, ['ewmac16']) ans8 = system6.combForecast.get_trading_rule_list("US10") self.assertEqual(ans8, ['ewmac16', 'ewmac8']) # missing
def futures_system(data=None, config=None, trading_rules=None, log_level="on"): """ :param data: data object (defaults to reading from csv files) :type data: sysdata.data.Data, or anything that inherits from it :param config: Configuration object (defaults to futuresconfig.yaml in this directory) :type config: sysdata.configdata.Config :param trading_rules: Set of trading rules to use (defaults to set specified in config object) :type trading_rules: list or dict of TradingRules, or something that can be parsed to that :param log_level: How much logging to do :type log_level: str >>> system=futures_system(log_level="off") >>> system System with stages: accounts, portfolio, positionSize, rawdata, combForecast, forecastScaleCap, rules >>> system.rules.get_raw_forecast("EDOLLAR", "ewmac2_8").dropna().head(2) ewmac2_8 1983-10-10 0.695929 1983-10-11 -0.604704 ewmac2_8 2015-04-21 0.172416 2015-04-22 -0.477559 >>> system.rules.get_raw_forecast("EDOLLAR", "carry").dropna().head(2) carry 1983-10-10 0.952297 1983-10-11 0.854075 carry 2015-04-21 0.350892 2015-04-22 0.350892 """ if data is None: data = csvFuturesData() if config is None: config = Config( "pysystemtrade.systems.provided.futures_chapter15.futuresconfig.yaml") rules = Rules(trading_rules) system = System([ Account(), Portfolios(), PositionSizing(), FuturesRawData(), ForecastCombine(), ForecastScaleCap(), rules ], data, config) system.set_logging_level(log_level) return system
def testCallingTradingRule(self): # config=Config(dict(trading_rules=dict(ewmac=dict(function="pysystemtrade.systems.provided.example.rules.ewmac_forecast_with_defaults")))) data = csvFuturesData("sysdata.tests") rawdata = RawData() rules = Rules() system = System([rawdata, rules], data) # Call with default data and config rule = TradingRule(ewmac_forecast_with_defaults) ans = rule.call(system, "EDOLLAR") self.assertAlmostEqual(ans.tail(1).values[0], 2.1384223788141838, 5) # Change the data source rule = TradingRule(( "pysystemtrade.systems.provided.example.rules.ewmac_forecast_with_defaults_no_vol", ["rawdata.get_daily_prices", "rawdata.daily_returns_volatility"], dict())) ans = rule.call(system, "EDOLLAR") self.assertAlmostEqual(ans.tail(1).values[0], 0.029376, 5) rule = TradingRule( dict( function= "pysystemtrade.systems.provided.example.rules.ewmac_forecast_with_defaults_no_vol", data=[ "rawdata.get_daily_prices", "rawdata.daily_returns_volatility" ], other_args=dict(Lfast=50, Lslow=200))) ans = rule.call(system, "EDOLLAR") self.assertAlmostEqual(ans.tail(1).values[0], 3.84426755)
def setUp(self): stage = SystemStage() stage.name = "test" data = Data() config = Config(dict(instruments=["another_code", "code"])) system = System([stage], data=data, config=config) self.system = system
def setUp(self): (accounts, fcs, rules, rawdata, data, config) = get_test_object_futures_with_rules_and_capping_estimate() system = System( [accounts, rawdata, rules, fcs, ForecastCombineEstimated()], data, config) setattr(self, "system", system)
def setUp(self): (rules, rawdata, data, config) = get_test_object_futures_with_rules() system = System([rawdata, rules, ForecastScaleCap()], data, config) self.system = system self.config = config self.rules = rules self.rawdata = rawdata self.forecast_scale_cap = ForecastScaleCap self.data = data
def test_get_forecast_scalar(self): # fixed ## From config self.assertEqual( self.system.forecastScaleCap.get_forecast_scalar( "EDOLLAR", "ewmac8"), 5.3) ## default config = copy.copy(self.config) unused = config.trading_rules['ewmac8'].pop('forecast_scalar') system2 = System([self.rawdata, self.rules, self.forecast_scale_cap()], self.data, config) self.assertEqual( system2.forecastScaleCap.get_forecast_scalar("EDOLLAR", "ewmac8"), 1.0) ## other config location setattr(config, 'forecast_scalars', dict(ewmac8=11.0)) system3 = System([self.rawdata, self.rules, self.forecast_scale_cap()], self.data, config) self.assertEqual( system3.forecastScaleCap.get_forecast_scalar("EDOLLAR", "ewmac8"), 11.0) # estimated config = copy.copy(self.config) config.use_forecast_scale_estimates = True system2 = System([self.rawdata, self.rules, self.forecast_scale_cap()], self.data, config) ## From default self.assertAlmostEqual(system2.forecastScaleCap.get_forecast_scalar( "EDOLLAR", "ewmac8").tail(1).values[0], 5.8, places=1) ## From config scale_config = dict(pool_instruments=False) config.forecast_scalar_estimate = scale_config system2 = System([self.rawdata, self.rules, self.forecast_scale_cap()], self.data, config) self.assertAlmostEqual( system2.forecastScaleCap.get_forecast_scalar( "EDOLLAR", "ewmac8").tail(1).values[0], 5.653444301)
def setUpWithEstimatedReturns(self): config = copy.copy(self.config) config.use_forecast_weight_estimates = True config.use_forecast_div_mult_estimates = True new_system = System([ self.rawdata, self.rules, self.fcs, self.forecast_combine(), Account() ], self.data, config) return new_system
def testCarryRule(self): data = csvFuturesData("sysdata.tests") rawdata = FuturesRawData() rules = Rules() system = System([rawdata, rules], data) rule = TradingRule(carry, [ "rawdata.daily_annualised_roll", "rawdata.daily_returns_volatility" ], dict(smooth_days=90)) ans = rule.call(system, "EDOLLAR") self.assertAlmostEqual(ans.tail(1).values[0], 0.411686026, 5)
def futures_system(data=None, config=None, trading_rules=None, log_level="terse"): """ :param data: data object (defaults to reading from csv files) :type data: sysdata.data.Data, or anything that inherits from it :param config: Configuration object (defaults to futuresconfig.yaml in this directory) :type config: sysdata.configdata.Config :param trading_rules: Set of trading rules to use (defaults to set specified in config object) :param trading_rules: list or dict of TradingRules, or something that can be parsed to that :param log_level: Set of trading rules to use (defaults to set specified in config object) :type log_level: str """ if data is None: data = csvFuturesData() if config is None: config = Config( "systems.provided.futures_chapter15.futuresestimateconfig.yaml") rules = Rules(trading_rules) system = System([ Account(), Portfolios(), PositionSizing(), FuturesRawData(), ForecastCombine(), ForecastScaleCap(), rules ], data, config) system.set_logging_level(log_level) return system
def test_get_forecast_cap(self): ans = self.system.forecastScaleCap.get_forecast_cap() self.assertEqual(ans, 21.0) ## test defaults config = self.config del (config.forecast_cap) system3 = System([self.rawdata, self.rules, self.forecast_scale_cap()], self.data, config) ans = system3.forecastScaleCap.get_forecast_cap() self.assertEqual(ans, 20.0)
def simplesystem(data=None, config=None, log_level="on"): """ Example of how to 'wrap' a complete system """ if config is None: config = Config("systems.provided.example.simplesystemconfig.yaml") if data is None: data = csvFuturesData() my_system = System([ Account(), Portfolios(), PositionSizing(), ForecastCombine(), ForecastScaleCap(), Rules() ], data, config) my_system.set_logging_level(log_level) return my_system
def test_get_price_volatility(self): self.assertAlmostEqual( self.system.positionSize.get_price_volatility("EDOLLAR").values[ -1], 0.059789159138) ## now without rawdata, should default to calculate on adj price system2 = System([ self.rules, self.fcs, self.forecast_combine, self.position_sizing() ], self.data, self.config) self.assertAlmostEqual( system2.positionSize.get_price_volatility("EDOLLAR").values[-1], 0.059723565)
def setUp(self): (fcs, rules, rawdata, data, config) = get_test_object_futures_with_rules_and_capping() system = System([rawdata, rules, fcs, ForecastCombine()], data, config) self.system = system self.config = config self.rules = rules self.rawdata = rawdata self.fcs = fcs self.forecast_combine = ForecastCombine self.data = data
def test_estimated_instrument_weights(self): config = copy.copy(self.config) config.use_instrument_weight_estimates = True system2 = System([ self.rawdata, self.rules, self.possizing, self.forecast_combine, self.fcs, Account(), self.portfolios() ], self.data, config) ans = system2.portfolio.get_instrument_weights() self.assertAlmostEqual(ans.BUND.values[-1], 0.541, places=2) self.assertAlmostEqual(ans.EDOLLAR.values[-1], 0.346, places=2) self.assertAlmostEqual(ans.US10.values[-1], 0.1121, places=2)
def setUp(self): (comb, fcs, rules, rawdata, data, config) = get_test_object_futures_with_comb_forecasts() system = System([rawdata, rules, fcs, comb, PositionSizing()], data, config) self.system = system self.config = config self.rules = rules self.rawdata = rawdata self.fcs = fcs self.forecast_combine = comb self.data = data self.position_sizing = PositionSizing
def test_actual_positions(self): config = copy.copy(self.config) config.use_instrument_weight_estimates = True system2 = System([ self.rawdata, self.rules, self.possizing, self.forecast_combine, self.fcs, Account(), self.portfolios() ], self.data, config) ans = system2.portfolio.get_actual_position("EDOLLAR") self.assertAlmostEqual(ans.values[-1], 1.058623, places=4) ans = system2.portfolio.get_actual_buffers_for_position("EDOLLAR") self.assertAlmostEqual(ans.values[-1][0], 1.164485, places=4) self.assertAlmostEqual(ans.values[-1][1], 0.952761, places=4)
def setUp(self): (posobject, combobject, capobject, rules, rawdata, data, config) = get_test_object_futures_with_pos_sizing() system = System( [rawdata, rules, posobject, combobject, capobject, Portfolios()], data, config) self.system = system self.config = config self.rules = rules self.rawdata = rawdata self.fcs = capobject self.forecast_combine = combobject self.data = data self.possizing = posobject self.portfolios = Portfolios
def test_estimated_dm(self): config = copy.copy(self.config) config.use_instrument_weight_estimates = True system2 = System([ self.rawdata, self.rules, self.possizing, self.forecast_combine, self.fcs, Account(), self.portfolios() ], self.data, config) ans = system2.portfolio.get_instrument_correlation_matrix( ).corr_list[-1] self.assertAlmostEqual(ans[0][1], 0.3889, places=3) self.assertAlmostEqual(ans[0][2], 0.5014, places=3) self.assertAlmostEqual(ans[1][2], 0.8771, places=3) ans = system2.portfolio.get_estimated_instrument_diversification_multiplier( ) self.assertAlmostEqual(ans.values[-1], 1.1855, places=3)
def test_get_daily_cash_vol_target(self): ans_dict = self.system.positionSize.get_daily_cash_vol_target() self.assertEqual(ans_dict['base_currency'], "GBP") self.assertEqual(ans_dict['annual_cash_vol_target'], 16000.0) self.assertEqual(ans_dict['daily_cash_vol_target'], 1000.0) self.assertEqual(ans_dict['notional_trading_capital'], 100000.0) self.assertEqual(ans_dict['percentage_vol_target'], 16.0) # test for missing config defaults system2 = System([ self.rawdata, self.rules, self.fcs, self.forecast_combine, self.position_sizing() ], self.data) ans_dict2 = system2.positionSize.get_daily_cash_vol_target() self.assertEqual(ans_dict2['base_currency'], "USD") self.assertEqual(ans_dict2['annual_cash_vol_target'], 160000.0) self.assertEqual(ans_dict2['daily_cash_vol_target'], 10000.0) self.assertEqual(ans_dict2['notional_trading_capital'], 1000000.0) self.assertEqual(ans_dict2['percentage_vol_target'], 16.0)
def update(self, message): """ Subscriber pattern main method. Will be called each time a registered event occurs. :param message: dict with instrument names as keys and pd.Dataframe as values. """ data = self.get_data(message) # Ib data Object. This is the Object that manage the data from ibAPI. my_data = ib_Data(data) # create a list with the instruments for the config object my_config = Config("private.config.yaml") # create a config object. my_config.instruments = my_data.get_instruments_list() # Setting the rules. my_rules = Rules(dict(ewmac=ewmac)) my_rules.trading_rules() # Initializing the system with all the stages. my_stages = [ Account(), Portfolios(), PositionSizing(), ForecastCombine(), ForecastScaleCap(), my_rules ] my_system = System(stage_list=my_stages, data=my_data, config=my_config) # Forecast for each instrument. for i in message.keys(): print("\n{} forecast:\n".format(i)) position = my_system.portfolio.get_notional_position(i) # Publishing forecast. message = dict(ticker=i, forecast=int(position.iloc[-1])) print(position.tail(5)) self.pub.dispatch(i, message)
def setUp(self): system = System([testStage1(), testStage2()], Data(), Config(dict(instruments=["code", "another_code"]))) self.system = system
def test_get_returns_for_optimisation(self): # Note: More thorough tests will be run inside optimisation module (FIXME next refactoring) # At this point we don't run proper tests but just check all the plumbing works with new caching code # FIXME rewrite proper tests once refactored optimisation generally system = self.setUpWithEstimatedReturns() print( system.combForecast.get_SR_cost_for_instrument_forecast( "EDOLLAR", "ewmac8")) print( system.combForecast.get_SR_cost_for_instrument_forecast( "BUND", "ewmac8")) print( system.combForecast.get_SR_cost_for_instrument_forecast( "US10", "ewmac8")) print(system.combForecast.has_same_cheap_rules_as_code("EDOLLAR")) print(system.combForecast.has_same_cheap_rules_as_code("BUND")) print(system.combForecast.has_same_cheap_rules_as_code("US10")) print( system.combForecast.get_returns_for_optimisation( "EDOLLAR").to_frame()) print( system.combForecast.get_returns_for_optimisation( "BUND").to_frame()) print( system.combForecast.get_returns_for_optimisation( "US10").to_frame()) print(system.combForecast.has_same_cheap_rules_as_code("EDOLLAR")) print(system.combForecast.has_same_cheap_rules_as_code("BUND")) print(system.combForecast.has_same_cheap_rules_as_code("US10")) # default - don't pool costs, pool gross print(system.combForecast.get_raw_forecast_weights("BUND")) # pool neithier gross or costs config = copy.copy(system.config) config.forecast_weight_estimate['pool_gross_returns'] = False config.forecast_weight_estimate['forecast_cost_estimates'] = False system2 = System([ self.rawdata, self.rules, self.fcs, self.forecast_combine(), Account() ], self.data, config) print(system2.combForecast.get_raw_forecast_weights("BUND")) # pool gross, not costs config = copy.copy(system.config) config.forecast_weight_estimate['pool_gross_returns'] = True config.forecast_weight_estimate['forecast_cost_estimates'] = False system2 = System([ self.rawdata, self.rules, self.fcs, self.forecast_combine(), Account() ], self.data, config) print(system2.combForecast.get_raw_forecast_weights("BUND")) # pool both (special function) config = copy.copy(system.config) config.forecast_weight_estimate['pool_gross_returns'] = True config.forecast_weight_estimate['forecast_cost_estimates'] = True system2 = System([ self.rawdata, self.rules, self.fcs, self.forecast_combine(), Account() ], self.data, config) print(system2.combForecast.get_raw_forecast_weights("BUND"))
def setUp(self): (rawdata, data, config) = get_test_object() system = System([rawdata], data) self.system = system