def portfolio_with_multiplier(self, delayfill=True, roundpositions=True): """ Get the p&l for entire portfolio using multiplied "actual" capital :param delayfill: Lag fills by one day :type delayfill: bool :param roundpositions: Round positions to whole contracts :type roundpositions: bool :returns: accountCurve """ self.log.terse("Calculating pandl for portfolio") capital = self.get_actual_capital(delayfill, roundpositions) instruments = self.get_instrument_list() port_pandl = [ self.pandl_for_instrument_with_multiplier( instrument_code, delayfill=delayfill, roundpositions=roundpositions) for instrument_code in instruments ] port_pandl = accountCurveGroup( port_pandl, instruments, capital=capital, weighted_flag=True) return port_pandl
def portfolio_with_multiplier(self, delayfill=True, roundpositions=True): """ Get the p&l for entire portfolio using multiplied "actual" capital :param delayfill: Lag fills by one day :type delayfill: bool :param roundpositions: Round positions to whole contracts :type roundpositions: bool :returns: accountCurve """ self.log.terse("Calculating pandl for portfolio") capital = self.get_actual_capital(delayfill, roundpositions) instruments = self.get_instrument_list() port_pandl = [ self.pandl_for_instrument_with_multiplier( instrument_code, delayfill=delayfill, roundpositions=roundpositions) for instrument_code in instruments ] port_pandl = accountCurveGroup(port_pandl, instruments, capital=capital, weighted_flag=True) return port_pandl
def _pandl_for_trading_rule_unweighted(system, instrument_code_unused, this_stage, rule_variation_name, delayfill): this_stage.log.terse( "Calculating pandl for trading rule (unweighted) %s" % rule_variation_name) instrument_list = system.get_instrument_list() instrument_list = [ instr_code for instr_code in instrument_list if rule_variation_name in this_stage.get_trading_rule_list( instr_code) ] pandl_by_instrument = [ this_stage.pandl_for_instrument_forecast( instr_code, rule_variation_name, delayfill) for instr_code in instrument_list ] pandl_rule = accountCurveGroup(pandl_by_instrument, instrument_list) return pandl_rule
def pandl_for_all_trading_rules_unweighted(self, delayfill=True): """ Get the p&l for all trading rules; unweighted Each trading rule has capital in isolation :param delayfill: Lag fills by one day :type delayfill: bool :returns: accountCurveGroup """ self.log.terse("Calculating pandl for all trading rules unweighted") variations = self.get_entire_trading_rule_list() # already weighted, don't need to do again pandl_by_trading_rule_unweighted = [ self.pandl_for_trading_rule(rulename, delayfill) for rulename in variations ] # this is a group of groups... will it work? pandl_all_rules = accountCurveGroup( pandl_by_trading_rule_unweighted, variations, capital=ARBITRARY_FORECAST_CAPITAL, weighted_flag=False, ) return pandl_all_rules
def pandl_for_all_trading_rules_unweighted(self, delayfill=True): """ Get the p&l for all trading rules; unweighted Each trading rule has capital in isolation :param delayfill: Lag fills by one day :type delayfill: bool :returns: accountCurveGroup """ self.log.terse("Calculating pandl for all trading rules unweighted") variations = self.get_entire_trading_rule_list() # already weighted, don't need to do again pandl_by_trading_rule_unweighted = [ self.pandl_for_trading_rule(rulename, delayfill) for rulename in variations ] # this is a group of groups... will it work? pandl_all_rules = accountCurveGroup( pandl_by_trading_rule_unweighted, variations, capital=ARBITRARY_FORECAST_CAPITAL, weighted_flag=False) return pandl_all_rules
def pandl_for_instrument_rules(self, instrument_code, delayfill=True): """ Get the p&l for one instrument over multiple forecasts; as % of arbitrary capital P&L are weighted by forecast weights and FDM KEY OUTPUT :param instrument_code: instrument to get values for :type instrument_code: str :param delayfill: Lag fills by one day :type delayfill: bool :returns: accountCurve >>> from systems.basesystem import System >>> from systems.tests.testdata import get_test_object_futures_with_portfolios >>> (portfolio, posobject, combobject, capobject, rules, rawdata, data, config)=get_test_object_futures_with_portfolios() >>> system=System([portfolio, posobject, combobject, capobject, rules, rawdata, Account()], data, config) >>> >>> system.accounts.pandl_for_instrument_rules_weighted("EDOLLAR").get_stats("sharpe") {'ewmac16': 0.6799720823590352, 'ewmac8': 0.69594671177102} """ self.log.terse( "Calculating pandl for instrument rules for %s" % instrument_code, instrument_code=instrument_code, ) forecast_rules = self.get_trading_rule_list(instrument_code) pandl_rules_unweighted = [ self.pandl_for_instrument_forecast( instrument_code, rule_variation_name, delayfill=delayfill ) for rule_variation_name in forecast_rules ] pandl_rules = [ weighted( pandl_this_rule, weighting=self.get_forecast_scaling_factor( instrument_code, rule_variation_name ), ) for (pandl_this_rule, rule_variation_name) in zip( pandl_rules_unweighted, forecast_rules ) ] pandl_rules = accountCurveGroup( pandl_rules, forecast_rules, capital=ARBITRARY_FORECAST_CAPITAL, weighted_flag=True, ) return pandl_rules
def pandl_for_instrument_rules(self, instrument_code, delayfill=True): """ Get the p&l for one instrument over multiple forecasts; as % of arbitrary capital P&L are weighted by forecast weights and FDM KEY OUTPUT :param instrument_code: instrument to get values for :type instrument_code: str :param delayfill: Lag fills by one day :type delayfill: bool :returns: accountCurve >>> from systems.basesystem import System >>> from systems.tests.testdata import get_test_object_futures_with_portfolios >>> (portfolio, posobject, combobject, capobject, rules, rawdata, data, config)=get_test_object_futures_with_portfolios() >>> system=System([portfolio, posobject, combobject, capobject, rules, rawdata, Account()], data, config) >>> >>> system.accounts.pandl_for_instrument_rules_weighted("EDOLLAR").get_stats("sharpe") {'ewmac16': 0.6799720823590352, 'ewmac8': 0.69594671177102} """ self.log.terse( "Calculating pandl for instrument rules for %s" % instrument_code, instrument_code=instrument_code) forecast_rules = self.get_trading_rule_list(instrument_code) pandl_rules_unweighted = [ self.pandl_for_instrument_forecast( instrument_code, rule_variation_name, delayfill=delayfill) for rule_variation_name in forecast_rules ] pandl_rules = [ weighted( pandl_this_rule, weighting=self.get_forecast_scaling_factor( instrument_code, rule_variation_name)) for (pandl_this_rule, rule_variation_name ) in zip(pandl_rules_unweighted, forecast_rules) ] pandl_rules = accountCurveGroup( pandl_rules, forecast_rules, capital=ARBITRARY_FORECAST_CAPITAL, weighted_flag=True) return pandl_rules
def pandl_for_instrument_rules_unweighted(self, instrument_code, rule_list=None, delayfill=True): """ Get the p&l for one instrument over multiple forecasts; as % of arbitrary capital All forecasting rules will have same expected std dev of returns; these aren't weighted KEY OUTPUT :param instrument_code: instrument to get values for :type instrument_code: str :param delayfill: Lag fills by one day :type delayfill: bool :returns: accountCurveGroup >>> from systems.basesystem import System >>> from systems.tests.testdata import get_test_object_futures_with_portfolios >>> (portfolio, posobject, combobject, capobject, rules, rawdata, data, config)=get_test_object_futures_with_portfolios() >>> system=System([portfolio, posobject, combobject, capobject, rules, rawdata, Account()], data, config) >>> >>> system.accounts.pandl_for_instrument_rules_unweighted("EDOLLAR").get_stats("sharpe") {'ewmac16': 0.6799720823590352, 'ewmac8': 0.69594671177102} """ self.log.terse( "Calculating pandl for instrument rules for %s" % instrument_code, instrument_code=instrument_code, ) if rule_list is None: rule_list = self.get_trading_rule_list(instrument_code) pandl_rules = [ self.pandl_for_instrument_forecast(instrument_code, rule_variation_name, delayfill=delayfill) for rule_variation_name in rule_list ] pandl_rules = accountCurveGroup( pandl_rules, rule_list, capital=ARBITRARY_FORECAST_CAPITAL, weighted_flag=False, ) return pandl_rules
def _pandl_across_subsystems( system, instrumentCodeNotUsed, this_stage, percentage, delayfill, roundpositions): instruments = this_stage.get_instrument_list() pandl_across_subsys = [ this_stage.pandl_for_subsystem( instrument_code, percentage=percentage, delayfill=delayfill, roundpositions=roundpositions) for instrument_code in instruments] pandl = accountCurveGroup(pandl_across_subsys, instruments) return pandl
def _pandl_across_subsystems(system, instrumentCodeNotUsed, this_stage, percentage, delayfill, roundpositions): instruments = this_stage.get_instrument_list() pandl_across_subsys = [ this_stage.pandl_for_subsystem(instrument_code, percentage=percentage, delayfill=delayfill, roundpositions=roundpositions) for instrument_code in instruments ] pandl = accountCurveGroup(pandl_across_subsys, instruments) return pandl
def pandl_for_instrument_rules_unweighted(self, instrument_code, rule_list=None, delayfill=True): """ Get the p&l for one instrument over multiple forecasts; as % of arbitrary capital All forecasting rules will have same expected std dev of returns; these aren't weighted KEY OUTPUT :param instrument_code: instrument to get values for :type instrument_code: str :param delayfill: Lag fills by one day :type delayfill: bool :returns: accountCurveGroup >>> from systems.basesystem import System >>> from systems.tests.testdata import get_test_object_futures_with_portfolios >>> (portfolio, posobject, combobject, capobject, rules, rawdata, data, config)=get_test_object_futures_with_portfolios() >>> system=System([portfolio, posobject, combobject, capobject, rules, rawdata, Account()], data, config) >>> >>> system.accounts.pandl_for_instrument_rules_unweighted("EDOLLAR").get_stats("sharpe") {'ewmac16': 0.6799720823590352, 'ewmac8': 0.69594671177102} """ self.log.terse( "Calculating pandl for instrument rules for %s" % instrument_code, instrument_code=instrument_code) if rule_list is None: rule_list = self.get_trading_rule_list(instrument_code) pandl_rules = [ self.pandl_for_instrument_forecast( instrument_code, rule_variation_name, delayfill=delayfill) for rule_variation_name in rule_list ] pandl_rules = accountCurveGroup( pandl_rules, rule_list, capital=ARBITRARY_FORECAST_CAPITAL, weighted_flag=False) return pandl_rules
def _portfolio(system, not_used, this_stage, percentage, delayfill, roundpositions): this_stage.log.terse("Calculating pandl for portfolio") instruments = this_stage.get_instrument_list() port_pandl = [ this_stage.pandl_for_instrument( instrument_code, percentage=percentage, delayfill=delayfill, roundpositions=roundpositions) for instrument_code in instruments] port_pandl = accountCurveGroup(port_pandl, instruments) return port_pandl
def _pandl_for_instrument_rules( system, instrument_code, this_stage, delayfill): this_stage.log.terse("Calculating pandl for instrument rules for %s" % instrument_code, instrument_code=instrument_code) forecast_rules=system.combForecast.get_trading_rule_list(instrument_code ) pandl_rules=[this_stage.pandl_for_instrument_forecast( instrument_code, rule_variation_name, delayfill) for rule_variation_name in forecast_rules ] pandl_rules = accountCurveGroup(pandl_rules, forecast_rules) return pandl_rules
def _portfolio(system, not_used, this_stage, percentage, delayfill, roundpositions): this_stage.log.terse("Calculating pandl for portfolio") instruments = this_stage.get_instrument_list() port_pandl = [ this_stage.pandl_for_instrument(instrument_code, percentage=percentage, delayfill=delayfill, roundpositions=roundpositions) for instrument_code in instruments ] port_pandl = accountCurveGroup(port_pandl, instruments) return port_pandl
def _pandl_for_trading_rule_unweighted( system, instrument_code_unused, this_stage, rule_variation_name, delayfill): this_stage.log.terse("Calculating pandl for trading rule (unweighted) %s" % rule_variation_name) instrument_list=system.get_instrument_list() instrument_list=[instr_code for instr_code in instrument_list if rule_variation_name in this_stage.get_trading_rule_list(instr_code)] pandl_by_instrument=[this_stage.pandl_for_instrument_forecast( instr_code, rule_variation_name, delayfill) for instr_code in instrument_list ] pandl_rule = accountCurveGroup(pandl_by_instrument, instrument_list) return pandl_rule
def pandl_across_subsystems(self, delayfill=True, roundpositions=False): """ Get the p&l across subsystems (unweighted) :param delayfill: Lag fills by one day :type delayfill: bool :param roundpositions: Round positions to whole contracts :type roundpositions: bool :returns: accountCurve >>> from systems.basesystem import System >>> from systems.tests.testdata import get_test_object_futures_with_portfolios >>> (portfolio, posobject, combobject, capobject, rules, rawdata, data, config)=get_test_object_futures_with_portfolios() >>> system=System([portfolio, posobject, combobject, capobject, rules, rawdata, Account()], data, config) >>> >>> system.accounts.pandl_across_subsystems().to_frame().tail(5) EDOLLAR US10 2015-12-07 0.001191 -0.005012 2015-12-08 0.000448 -0.002395 2015-12-09 0.000311 -0.002797 2015-12-10 -0.002384 0.003957 2015-12-11 0.004835 -0.007594 """ # Subsystems use entire capital capital = self.get_notional_capital() instruments = self.get_instrument_list() pandl_across_subsys = [ self.pandl_for_subsystem( instrument_code, delayfill=delayfill, roundpositions=roundpositions) for instrument_code in instruments ] pandl = accountCurveGroup( pandl_across_subsys, instruments, capital=capital, weighted_flag=False) return pandl
def pandl_for_trading_rule_weighted( self, rule_variation_name, delayfill=True): """ Get the p&l for one trading rule over multiple instruments; as % of total capital Within the trading rule the instrument returns are weighted by risk contribution :param rule_variation_name: rule to get values for :type rule_variation_name: str :param delayfill: Lag fills by one day :type delayfill: bool :returns: accountCurveGroup """ self.log.terse( "Calculating pandl for trading rule %s" % rule_variation_name) instrument_list = self.parent.get_instrument_list() instrument_list = [ instr_code for instr_code in instrument_list if rule_variation_name in self.get_trading_rule_list(instr_code) ] # already weighted, don't need to do again pandl_by_instrument_weighted = [ self.pandl_for_instrument_forecast_weighted( instr_code, rule_variation_name, delayfill ) for instr_code in instrument_list ] pandl_rule = accountCurveGroup( pandl_by_instrument_weighted, instrument_list, capital=ARBITRARY_FORECAST_CAPITAL, weighted_flag=True, ) return pandl_rule
def pandl_for_trading_rule_unweighted( self, rule_variation_name, delayfill=True): """ Get the p&l for one trading rule over multiple instruments; as % of arbitrary capital Within the trading rule the instrument returns are NOT weighted by instrument weight :param rule_variation_name: rule to get values for :type rule_variation_name: str :param delayfill: Lag fills by one day :type delayfill: bool :returns: accountCurve """ self.log.terse( "Calculating pandl for trading rule (unweighted) %s" % rule_variation_name) instrument_list = self.parent.get_instrument_list() instrument_list = [ instr_code for instr_code in instrument_list if rule_variation_name in self.get_trading_rule_list(instr_code) ] pandl_by_instrument = [ self.pandl_for_instrument_forecast( instr_code, rule_variation_name, delayfill ) for instr_code in instrument_list ] pandl_rule = accountCurveGroup( pandl_by_instrument, instrument_list, capital=ARBITRARY_FORECAST_CAPITAL, weighted_flag=False, ) return pandl_rule
def _pandl_for_instrument_rules_unweighted(system, instrument_code, this_stage, delayfill): this_stage.log.terse( "Calculating pandl for instrument rules for %s" % instrument_code, instrument_code=instrument_code) forecast_rules = this_stage.get_trading_rule_list(instrument_code) pandl_rules = [ this_stage.pandl_for_instrument_forecast(instrument_code, rule_variation_name, delayfill=delayfill, weighting=None) for rule_variation_name in forecast_rules ] pandl_rules = accountCurveGroup(pandl_rules, forecast_rules) return pandl_rules
def pandl_for_trading_rule_weighted(self, rule_variation_name, delayfill=True): """ Get the p&l for one trading rule over multiple instruments; as % of total capital Within the trading rule the instrument returns are weighted by risk contribution :param rule_variation_name: rule to get values for :type rule_variation_name: str :param delayfill: Lag fills by one day :type delayfill: bool :returns: accountCurveGroup """ self.log.terse( "Calculating pandl for trading rule %s" % rule_variation_name) instrument_list = self.parent.get_instrument_list() instrument_list = [ instr_code for instr_code in instrument_list if rule_variation_name in self.get_trading_rule_list(instr_code) ] # already weighted, don't need to do again pandl_by_instrument_weighted = [ self.pandl_for_instrument_forecast_weighted( instr_code, rule_variation_name, delayfill) for instr_code in instrument_list ] pandl_rule = accountCurveGroup( pandl_by_instrument_weighted, instrument_list, capital=ARBITRARY_FORECAST_CAPITAL, weighted_flag=True) return pandl_rule
def pandl_for_trading_rule_unweighted(self, rule_variation_name, delayfill=True): """ Get the p&l for one trading rule over multiple instruments; as % of arbitrary capital Within the trading rule the instrument returns are NOT weighted by instrument weight :param rule_variation_name: rule to get values for :type rule_variation_name: str :param delayfill: Lag fills by one day :type delayfill: bool :returns: accountCurve """ self.log.terse("Calculating pandl for trading rule (unweighted) %s" % rule_variation_name) instrument_list = self.parent.get_instrument_list() instrument_list = [ instr_code for instr_code in instrument_list if rule_variation_name in self.get_trading_rule_list(instr_code) ] pandl_by_instrument = [ self.pandl_for_instrument_forecast(instr_code, rule_variation_name, delayfill) for instr_code in instrument_list ] pandl_rule = accountCurveGroup( pandl_by_instrument, instrument_list, capital=ARBITRARY_FORECAST_CAPITAL, weighted_flag=False) return pandl_rule
def portfolio(self, delayfill=True, roundpositions=True): """ Get the p&l for entire portfolio :param delayfill: Lag fills by one day :type delayfill: bool :param roundpositions: Round positions to whole contracts :type roundpositions: bool :returns: accountCurve >>> from systems.basesystem import System >>> from systems.tests.testdata import get_test_object_futures_with_portfolios >>> (portfolio, posobject, combobject, capobject, rules, rawdata, data, config)=get_test_object_futures_with_portfolios() >>> system=System([portfolio, posobject, combobject, capobject, rules, rawdata, Account()], data, config) >>> >>> system.accounts.portfolio().ann_std() 0.2638225179274214 """ self.log.terse("Calculating pandl for portfolio") capital = self.get_notional_capital() instruments = self.get_instrument_list() port_pandl = [ self.pandl_for_instrument(instrument_code, delayfill=delayfill, roundpositions=roundpositions) for instrument_code in instruments ] port_pandl = accountCurveGroup(port_pandl, instruments, capital=capital, weighted_flag=True) return port_pandl
def portfolio(self, delayfill=True, roundpositions=True): """ Get the p&l for entire portfolio :param delayfill: Lag fills by one day :type delayfill: bool :param roundpositions: Round positions to whole contracts :type roundpositions: bool :returns: accountCurve >>> from systems.basesystem import System >>> from systems.tests.testdata import get_test_object_futures_with_portfolios >>> (portfolio, posobject, combobject, capobject, rules, rawdata, data, config)=get_test_object_futures_with_portfolios() >>> system=System([portfolio, posobject, combobject, capobject, rules, rawdata, Account()], data, config) >>> >>> system.accounts.portfolio().ann_std() 0.2638225179274214 """ self.log.terse("Calculating pandl for portfolio") capital = self.get_notional_capital() instruments = self.get_instrument_list() port_pandl = [ self.pandl_for_instrument( instrument_code, delayfill=delayfill, roundpositions=roundpositions) for instrument_code in instruments ] port_pandl = accountCurveGroup( port_pandl, instruments, capital=capital, weighted_flag=True) return port_pandl
def pandl_for_trading_rule(self, rule_variation_name, delayfill=True): """ Get the p&l for one trading rule over multiple instruments; as % of its risk contribution Within the trading rule the instrument returns are weighted by instrument weight :param rule_variation_name: rule to get values for :type rule_variation_name: str :param delayfill: Lag fills by one day :type delayfill: bool :returns: accountCurve """ self.log.terse("Calculating pandl for trading rule %s" % rule_variation_name) instrument_list = self.parent.get_instrument_list() instrument_list = [ instr_code for instr_code in instrument_list if rule_variation_name in self.get_trading_rule_list(instr_code) ] # already weighted # capital on these will be the default pandl_by_instrument_weighted = [ self.pandl_for_instrument_forecast_weighted( instr_code, rule_variation_name, delayfill) for instr_code in instrument_list ] # now we weight so total capital is correct capital_this_rule = self.get_capital_in_rule(rule_variation_name) def _cleanweightelement(capelement): if np.isnan(capelement): return 0.0 if capelement == 0.0: return 0.0 else: return 1.0 / capelement weight = [ _cleanweightelement(capelement) for capelement in list(capital_this_rule.values) ] weight = pd.Series(weight, index=capital_this_rule.index) pandl_by_instrument_reweighted = [ weighted(pandl_for_instrument, weight, allow_reweighting=True) for pandl_for_instrument in pandl_by_instrument_weighted ] pandl_rule = accountCurveGroup( pandl_by_instrument_reweighted, instrument_list, capital=ARBITRARY_FORECAST_CAPITAL, weighted_flag=True, ) return pandl_rule
def pandl_for_trading_rule(self, rule_variation_name, delayfill=True): """ Get the p&l for one trading rule over multiple instruments; as % of its risk contribution Within the trading rule the instrument returns are weighted by instrument weight :param rule_variation_name: rule to get values for :type rule_variation_name: str :param delayfill: Lag fills by one day :type delayfill: bool :returns: accountCurve """ self.log.terse( "Calculating pandl for trading rule %s" % rule_variation_name) instrument_list = self.parent.get_instrument_list() instrument_list = [ instr_code for instr_code in instrument_list if rule_variation_name in self.get_trading_rule_list(instr_code) ] # already weighted # capital on these will be the default pandl_by_instrument_weighted = [ self.pandl_for_instrument_forecast_weighted( instr_code, rule_variation_name, delayfill) for instr_code in instrument_list ] # now we weight so total capital is correct capital_this_rule = self.get_capital_in_rule(rule_variation_name) def _cleanweightelement(capelement): if np.isnan(capelement): return 0.0 if capelement == 0.0: return 0.0 else: return 1.0 / capelement weight = [ _cleanweightelement(capelement) for capelement in list(capital_this_rule.values) ] weight = pd.Series(weight, index=capital_this_rule.index) pandl_by_instrument_reweighted = [ weighted(pandl_for_instrument, weight, allow_reweighting=True) for pandl_for_instrument in pandl_by_instrument_weighted ] pandl_rule = accountCurveGroup( pandl_by_instrument_reweighted, instrument_list, capital=ARBITRARY_FORECAST_CAPITAL, weighted_flag=True) return pandl_rule