Beispiel #1
0
    def pandl_across_subsystems(self,
                                percentage=True,
                                delayfill=True,
                                roundpositions=False):
        """
        Get the p&l across subsystems

        :param percentage: Return results as % of total notional capital
        :type percentage: bool

        :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(percentage=True).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
        """
        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

        itemname = "pandl_across_subsystems__percentage%sdelayfill%sroundpositions%s" % (
            TorF(percentage), TorF(delayfill), TorF(roundpositions))
        instr_pandl = self.parent.calc_or_cache(itemname, ALL_KEYNAME,
                                                _pandl_across_subsystems, self,
                                                percentage, delayfill,
                                                roundpositions)

        return instr_pandl
Beispiel #2
0
    def portfolio(self, percentage=True, delayfill=True, roundpositions=False):
        """
        Get the p&l for entire portfolio

        :param percentage: Return results as % of total notional capital
        :type percentage: bool

        :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)
        >>>
        >>> round(system.accounts.portfolio(percentage=True).std()*16,3)
        0.28199999999999997
        >>> round(system.accounts.portfolio(percentage=False).std()*16/100000.0,3)
        0.28199999999999997
        """
        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 = pd.concat(port_pandl, axis=1).sum(axis=1)
            port_pandl = accountCurve(port_pandl)

            return port_pandl

        itemname = "portfolio__percentage%sdelayfill%sroundpositions%s" % (
            TorF(percentage), TorF(delayfill), TorF(roundpositions))

        port_pandl = self.parent.calc_or_cache(itemname, ALL_KEYNAME,
                                               _portfolio, self, percentage,
                                               delayfill, roundpositions)

        return port_pandl
Beispiel #3
0
    def instrument_turnover(self, instrument_code, roundpositions=True):
        """
        Get the annualised turnover for an instrument

        :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

        :returns: float


        """
        def _instrument_turnover(system, instrument_code, this_stage,
                                 roundpositions):

            average_position_for_turnover = multiply_df_single_column(
                this_stage.get_volatility_scalar(instrument_code),
                this_stage.get_instrument_scaling_factor(instrument_code),
                ffill=(True, True))

            positions = this_stage.get_buffered_position(
                instrument_code, roundpositions=roundpositions)

            return turnover(positions, average_position_for_turnover)

        instr_turnover = self.parent.calc_or_cache(
            "instrument_turnover_%s" % TorF(roundpositions), instrument_code,
            _instrument_turnover, self, roundpositions)

        return instr_turnover
Beispiel #4
0
    def subsystem_turnover(self, instrument_code, roundpositions):
        """
        Get the annualised turnover for an instrument subsystem

        :param instrument_code: instrument to get values for
        :type instrument_code: str

        :returns: float


        """
        def _subsystem_turnover(system, instrument_code, this_stage,
                                roundpositions):

            positions = this_stage.get_subsystem_position(instrument_code)
            average_position_for_turnover = this_stage.get_volatility_scalar(
                instrument_code)

            return turnover(positions, average_position_for_turnover)

        subsys_turnover = self.parent.calc_or_cache(
            "subsystem_turnover_%s" % TorF(roundpositions), instrument_code,
            _subsystem_turnover, self, roundpositions)

        return subsys_turnover
Beispiel #5
0
    def pandl_for_instrument_rules_unweighted(self,
                                              instrument_code,
                                              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: 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_unweighted("EDOLLAR").get_stats("sharpe")
        {'ewmac16': 0.6799720823590352, 'ewmac8': 0.69594671177102}
        """
        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

        itemname = "pandl_for_instrument_rules_unweighted_delayfill%s" % TorF(
            delayfill)

        pandl_rules = self.parent.calc_or_cache(
            itemname, instrument_code, _pandl_for_instrument_rules_unweighted,
            self, delayfill)

        return pandl_rules
Beispiel #6
0
    def pandl_for_instrument_rules(self, instrument_code, delayfill=True):
        """
        Get the p&l for one instrument over multiple forecasts; as % of arbitrary capital
        
        KEY OUTPUT

        :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

        >>> 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("EDOLLAR")
        wibble

        """
        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 = pd.concat([
                this_stage.pandl_for_instrument_forecast(
                    instrument_code, rule_variation_name, delayfill)
                for rule_variation_name in forecast_rules
            ],
                                    axis=1)

            pandl_rules.columns = forecast_rules

            return pandl_rules

        itemname = "pandl_for_instrument__rules_delayfill%s" % TorF(delayfill)

        pandl_rules = self.parent.calc_or_cache(itemname, instrument_code,
                                                _pandl_for_instrument_rules,
                                                self, delayfill)

        return pandl_rules
Beispiel #7
0
    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

        """
        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

        itemname = "pandl_for_trading_rule_unweighted_%s_delayfill%s" % (
            rule_variation_name, TorF(delayfill))

        pandl_trading_rule_unweighted = self.parent.calc_or_cache(
            itemname, ALL_KEYNAME, _pandl_for_trading_rule_unweighted, self,
            rule_variation_name, delayfill)

        return pandl_trading_rule_unweighted
Beispiel #8
0
    def get_buffered_position(self, instrument_code, roundpositions=True):
        """
        Get the buffered position

        :param instrument_code: instrument to get
        :type percentage: bool

        :param roundpositions: Round positions to whole contracts
        :type roundpositions: bool

        :returns: Tx1 pd.DataFrame

        >>> 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.get_buffered_position("EDOLLAR").tail(3)
                    position
        2015-12-09         1
        2015-12-10         1
        2015-12-11         1
        """
        def _get_buffered_position(system, instrument_code, this_stage,
                                   roundpositions):

            this_stage.log.msg("Calculating buffered positions")
            optimal_position = this_stage.get_notional_position(
                instrument_code)
            pos_buffers = this_stage.get_buffers_for_position(instrument_code)
            trade_to_edge = system.config.buffer_trade_to_edge

            buffered_position = apply_buffer(optimal_position,
                                             pos_buffers,
                                             trade_to_edge=trade_to_edge,
                                             roundpositions=roundpositions)

            buffered_position.columns = ["position"]

            return buffered_position

        itemname = "get_buffered_position__roundpositions%s" % TorF(
            roundpositions)

        buffered_position = self.parent.calc_or_cache(itemname,
                                                      instrument_code,
                                                      _get_buffered_position,
                                                      self, roundpositions)

        return buffered_position
Beispiel #9
0
    def pandl_for_instrument_forecast(self,
                                      instrument_code,
                                      rule_variation_name,
                                      delayfill=True):
        """
        Get the p&l for one instrument and forecast; as % of arbitrary capital

        KEY OUTPUT:

        :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

        >>> 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)
        >>>
        >>> round(system.accounts.pandl_for_instrument_forecast("EDOLLAR", "ewmac8").std()*16,3)
        0.20999999999999999

        """
        def _pandl_for_instrument_forecast(system, instrument_code,
                                           rule_variation_name, this_stage,
                                           delayfill):

            this_stage.log.msg(
                "Calculating pandl for instrument forecast for %s %s" %
                (instrument_code, rule_variation_name),
                instrument_code=instrument_code,
                rule_variation_name=rule_variation_name)

            price = this_stage.get_daily_price(instrument_code)
            forecast = this_stage.get_capped_forecast(instrument_code,
                                                      rule_variation_name)
            get_daily_returns_volatility = this_stage.get_daily_returns_volatility(
                instrument_code)

            pandl_fcast = pandl(
                price=price,
                delayfill=delayfill,
                get_daily_returns_volatility=get_daily_returns_volatility,
                forecast=forecast,
                capital=0.0)
            return pandl_fcast

        itemname = "pandl_for_instrument__forecast_delayfill%s" % TorF(
            delayfill)

        pandl_fcast = self.parent.calc_or_cache_nested(
            itemname, instrument_code, rule_variation_name,
            _pandl_for_instrument_forecast, self, delayfill)

        return pandl_fcast
Beispiel #10
0
    def pandl_for_instrument(self,
                             instrument_code,
                             percentage=True,
                             delayfill=True,
                             roundpositions=False):
        """
        Get the p&l for one instrument

        :param instrument_code: instrument to get values for
        :type instrument_code: str

        :param percentage: Return results as % of total notional capital
        :type percentage: bool

        :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)
        >>>
        >>> round(system.accounts.pandl_for_instrument("US10", percentage=False).std()*16/100000.0,3)
        0.14299999999999999
        >>> round(system.accounts.pandl_for_instrument("EDOLLAR", percentage=False).std()*16/100000.0,3)
        0.152
        >>> round(system.accounts.pandl_for_instrument("US10", percentage=True).std()*16,3)
        0.14299999999999999
        """
        def _pandl_for_instrument(system, instrument_code, this_stage,
                                  percentage, delayfill, roundpositions):

            this_stage.log.msg("Calculating pandl for instrument for %s" %
                               instrument_code,
                               instrument_code=instrument_code)

            price = this_stage.get_daily_price(instrument_code)
            positions = this_stage.get_notional_position(instrument_code)
            fx = this_stage.get_fx_rate(instrument_code)
            value_of_price_point = this_stage.get_value_of_price_move(
                instrument_code)

            if percentage:
                capital = this_stage.get_notional_capital()
            else:
                capital = None

            instr_pandl = pandl(price=price,
                                positions=positions,
                                delayfill=delayfill,
                                roundpositions=roundpositions,
                                fx=fx,
                                value_of_price_point=value_of_price_point,
                                capital=capital)

            return instr_pandl

        itemname = "pandl_for_instrument__percentage%sdelayfill%sroundpositions%s" % (
            TorF(percentage), TorF(delayfill), TorF(roundpositions))
        instr_pandl = self.parent.calc_or_cache(itemname, instrument_code,
                                                _pandl_for_instrument, self,
                                                percentage, delayfill,
                                                roundpositions)

        return instr_pandl
Beispiel #11
0
    def pandl_for_instrument(self,
                             instrument_code,
                             percentage=True,
                             delayfill=True,
                             roundpositions=True):
        """
        Get the p&l for one instrument

        :param instrument_code: instrument to get values for
        :type instrument_code: str

        :param percentage: Return results as % of total notional capital
        :type percentage: bool

        :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", percentage=True).ann_std()
        0.13908407620762306
        """
        def _pandl_for_instrument(system, instrument_code, this_stage,
                                  percentage, delayfill, roundpositions):

            this_stage.log.msg("Calculating pandl for instrument for %s" %
                               instrument_code,
                               instrument_code=instrument_code)

            price = this_stage.get_daily_price(instrument_code)
            positions = this_stage.get_buffered_position(
                instrument_code, roundpositions=roundpositions)
            fx = this_stage.get_fx_rate(instrument_code)
            value_of_price_point = this_stage.get_value_of_price_move(
                instrument_code)
            get_daily_returns_volatility = this_stage.get_daily_returns_volatility(
                instrument_code)

            capital = this_stage.get_notional_capital()
            ann_risk_target = this_stage.get_ann_risk_target()

            (SR_cost, cash_costs) = this_stage.get_costs(instrument_code)

            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 = this_stage.instrument_turnover(
                    instrument_code, roundpositions=roundpositions)
                SR_cost = SR_cost * turnover_for_SR
                weighting = this_stage.get_instrument_scaling_factor(
                    instrument_code)
                apply_weight_to_costs_only = True
            else:
                ## Costs wil be correct
                ## We don't need to do anything
                weighting = None
                apply_weight_to_costs_only = False

            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,
                percentage=percentage,
                SR_cost=SR_cost,
                cash_costs=cash_costs,
                get_daily_returns_volatility=get_daily_returns_volatility,
                weighting=weighting,
                apply_weight_to_costs_only=apply_weight_to_costs_only)

            return instr_pandl

        itemname = "pandl_for_instrument__percentage%sdelayfill%sroundpositions%s" % (
            TorF(percentage), TorF(delayfill), TorF(roundpositions))
        instr_pandl = self.parent.calc_or_cache(itemname, instrument_code,
                                                _pandl_for_instrument, self,
                                                percentage, delayfill,
                                                roundpositions)

        return instr_pandl
Beispiel #12
0
    def pandl_for_subsystem(self,
                            instrument_code,
                            percentage=True,
                            delayfill=True,
                            roundpositions=False):
        """
        Get the p&l for one instrument

        :param instrument_code: instrument to get values for
        :type instrument_code: str

        :param percentage: Return results as % of total notional capital
        :type percentage: bool

        :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_subsystem("US10", percentage=True).ann_std()
        0.23422378634127036
        """
        def _pandl_for_subsystem(system, instrument_code, this_stage,
                                 percentage, delayfill, roundpositions):

            this_stage.log.msg(
                "Calculating pandl for subsystem for instrument %s" %
                instrument_code,
                instrument_code=instrument_code)

            price = this_stage.get_daily_price(instrument_code)
            positions = this_stage.get_subsystem_position(instrument_code)

            fx = this_stage.get_fx_rate(instrument_code)
            value_of_price_point = this_stage.get_value_of_price_move(
                instrument_code)
            get_daily_returns_volatility = this_stage.get_daily_returns_volatility(
                instrument_code)

            (SR_cost, cash_costs) = this_stage.get_costs(instrument_code)

            if SR_cost is not None:
                turnover_for_SR = this_stage.subsystem_turnover(
                    instrument_code, roundpositions=roundpositions)
                SR_cost = SR_cost * turnover_for_SR

            capital = this_stage.get_notional_capital()
            ann_risk_target = this_stage.get_ann_risk_target()

            instr_pandl = accountCurve(
                price,
                positions=positions,
                delayfill=delayfill,
                roundpositions=roundpositions,
                fx=fx,
                value_of_price_point=value_of_price_point,
                capital=capital,
                percentage=percentage,
                SR_cost=SR_cost,
                cash_costs=cash_costs,
                get_daily_returns_volatility=get_daily_returns_volatility,
                ann_risk_target=ann_risk_target)

            return instr_pandl

        itemname = "pandl_for_subsystem__percentage%sdelayfill%sroundpositions%s" % (
            TorF(percentage), TorF(delayfill), TorF(roundpositions))
        instr_pandl = self.parent.calc_or_cache(itemname, instrument_code,
                                                _pandl_for_subsystem, self,
                                                percentage, delayfill,
                                                roundpositions)

        return instr_pandl