def pandl_for_instrument_forecast_weighted(self, instrument_code, rule_variation_name, delayfill=True): """ Get the p&l for one instrument and forecast; as % of total capital :param instrument_code: instrument to get values for :type instrument_code: str :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.msg( "Calculating pandl for instrument forecast weighted for %s %s" % (instrument_code, rule_variation_name), instrument_code=instrument_code, rule_variation_name=rule_variation_name) pandl = self.pandl_for_instrument_forecast( instrument_code, rule_variation_name, delayfill=delayfill) weight = self.get_instrument_forecast_scaling_factor( instrument_code, rule_variation_name) pandl = weighted(pandl, weight) return pandl
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_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_instrument(self, instrument_code, delayfill=True, roundpositions=True): """ Get the p&l for one instrument :param instrument_code: instrument to get values for :type instrument_code: str :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_for_instrument("US10").ann_std() 0.13908407620762306 """ self.log.msg( "Calculating pandl for instrument for %s" % instrument_code, instrument_code=instrument_code, ) price = self.get_daily_price(instrument_code) positions = self.get_buffered_position(instrument_code, roundpositions=roundpositions) fx = self.get_fx_rate(instrument_code) value_of_price_point = self.get_value_of_price_move(instrument_code) get_daily_returns_volatility = self.get_daily_returns_volatility( instrument_code) capital = self.get_notional_capital() ann_risk_target = self.get_ann_risk_target() (SR_cost, cash_costs) = self.get_costs(instrument_code) instr_pandl = accountCurve( price, positions=positions, delayfill=delayfill, roundpositions=roundpositions, fx=fx, value_of_price_point=value_of_price_point, capital=capital, ann_risk_target=ann_risk_target, SR_cost=SR_cost, cash_costs=cash_costs, get_daily_returns_volatility=get_daily_returns_volatility, ) if SR_cost is not None: # Note that SR cost is done as a proportion of capital # Since we're only using part of the capital we need to correct # for this turnover_for_SR = self.instrument_turnover( instrument_code, roundpositions=roundpositions) SR_cost = SR_cost * turnover_for_SR weighting = self.get_instrument_scaling_factor(instrument_code) apply_weight_to_costs_only = True instr_pandl = weighted( instr_pandl, weighting=weighting, apply_weight_to_costs_only=apply_weight_to_costs_only, ) else: # Costs wil be correct # We don't need to do anything pass return instr_pandl
def pandl_for_instrument_with_multiplier(self, instrument_code, delayfill=True, roundpositions=True): """ Get the p&l for one instrument, using variable capital :param instrument_code: instrument to get values for :type instrument_code: str :param delayfill: Lag fills by one day :type delayfill: bool :param roundpositions: Round positions to whole contracts :type roundpositions: bool :returns: accountCurve """ self.log.msg( "Calculating pandl for instrument for %s with capital multiplier" % instrument_code, instrument_code=instrument_code, ) price = self.get_daily_price(instrument_code) positions = self.get_buffered_position_with_multiplier( instrument_code, roundpositions=roundpositions) fx = self.get_fx_rate(instrument_code) value_of_price_point = self.get_value_of_price_move(instrument_code) get_daily_returns_volatility = self.get_daily_returns_volatility( instrument_code) capital = self.get_actual_capital(delayfill=delayfill, roundpositions=roundpositions) ann_risk_target = self.get_ann_risk_target() (SR_cost, cash_costs) = self.get_costs(instrument_code) instr_pandl = accountCurve( price, positions=positions, delayfill=delayfill, roundpositions=roundpositions, fx=fx, value_of_price_point=value_of_price_point, capital=capital, ann_risk_target=ann_risk_target, SR_cost=SR_cost, cash_costs=cash_costs, get_daily_returns_volatility=get_daily_returns_volatility, ) if SR_cost is not None: # Note that SR cost is done as a proportion of capital # Since we're only using part of the capital we need to correct # for this turnover_for_SR = self.instrument_turnover( instrument_code, roundpositions=roundpositions) SR_cost = SR_cost * turnover_for_SR weighting = self.get_instrument_scaling_factor(instrument_code) apply_weight_to_costs_only = True instr_pandl = weighted( instr_pandl, weighting=weighting, apply_weight_to_costs_only=apply_weight_to_costs_only, ) else: # Costs wil be correct # We don't need to do anything pass return instr_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_instrument(self, instrument_code, delayfill=True, roundpositions=True): """ Get the p&l for one instrument :param instrument_code: instrument to get values for :type instrument_code: str :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_for_instrument("US10").ann_std() 0.13908407620762306 """ self.log.msg( "Calculating pandl for instrument for %s" % instrument_code, instrument_code=instrument_code) price = self.get_daily_price(instrument_code) positions = self.get_buffered_position( instrument_code, roundpositions=roundpositions) fx = self.get_fx_rate(instrument_code) value_of_price_point = self.get_value_of_price_move(instrument_code) get_daily_returns_volatility = self.get_daily_returns_volatility( instrument_code) capital = self.get_notional_capital() ann_risk_target = self.get_ann_risk_target() (SR_cost, cash_costs) = self.get_costs(instrument_code) instr_pandl = accountCurve( price, positions=positions, delayfill=delayfill, roundpositions=roundpositions, fx=fx, value_of_price_point=value_of_price_point, capital=capital, ann_risk_target=ann_risk_target, SR_cost=SR_cost, cash_costs=cash_costs, get_daily_returns_volatility=get_daily_returns_volatility) if SR_cost is not None: # Note that SR cost is done as a proportion of capital # Since we're only using part of the capital we need to correct # for this turnover_for_SR = self.instrument_turnover( instrument_code, roundpositions=roundpositions) SR_cost = SR_cost * turnover_for_SR weighting = self.get_instrument_scaling_factor(instrument_code) apply_weight_to_costs_only = True instr_pandl = weighted( instr_pandl, weighting=weighting, apply_weight_to_costs_only=apply_weight_to_costs_only) else: # Costs wil be correct # We don't need to do anything pass return instr_pandl
def pandl_for_instrument_with_multiplier(self, instrument_code, delayfill=True, roundpositions=True): """ Get the p&l for one instrument, using variable capital :param instrument_code: instrument to get values for :type instrument_code: str :param delayfill: Lag fills by one day :type delayfill: bool :param roundpositions: Round positions to whole contracts :type roundpositions: bool :returns: accountCurve """ self.log.msg( "Calculating pandl for instrument for %s with capital multiplier" % instrument_code, instrument_code=instrument_code) price = self.get_daily_price(instrument_code) positions = self.get_buffered_position_with_multiplier( instrument_code, roundpositions=roundpositions) fx = self.get_fx_rate(instrument_code) value_of_price_point = self.get_value_of_price_move(instrument_code) get_daily_returns_volatility = self.get_daily_returns_volatility( instrument_code) capital = self.get_actual_capital( delayfill=delayfill, roundpositions=roundpositions) ann_risk_target = self.get_ann_risk_target() (SR_cost, cash_costs) = self.get_costs(instrument_code) instr_pandl = accountCurve( price, positions=positions, delayfill=delayfill, roundpositions=roundpositions, fx=fx, value_of_price_point=value_of_price_point, capital=capital, ann_risk_target=ann_risk_target, SR_cost=SR_cost, cash_costs=cash_costs, get_daily_returns_volatility=get_daily_returns_volatility) if SR_cost is not None: # Note that SR cost is done as a proportion of capital # Since we're only using part of the capital we need to correct # for this turnover_for_SR = self.instrument_turnover( instrument_code, roundpositions=roundpositions) SR_cost = SR_cost * turnover_for_SR weighting = self.get_instrument_scaling_factor(instrument_code) apply_weight_to_costs_only = True instr_pandl = weighted( instr_pandl, weighting=weighting, apply_weight_to_costs_only=apply_weight_to_costs_only) else: # Costs wil be correct # We don't need to do anything pass return instr_pandl