Exemplo n.º 1
0
    def __init__(self):
        '''

        '''

        # We set these to empty lists but in the inherited object they'll be
        # overriden
        setattr(self, "_protected", [])
        setattr(self, "name", self._name())
        setattr(self, "description", self._description())

        # this will normally be overriden by the base system when we call _system_init
        setattr(self, "log", logtoscreen(stage="config"))
Exemplo n.º 2
0
    def __init__(self, config_object=dict()):
        """
        Config objects control the behaviour of systems

        :param config_object: Either:
                        a string (which points to a YAML filename)
                        or a dict (which may nest many things)
                        or a list of strings or dicts (build config from
                        multiple elements, latter elements will overwrite
                        earlier oness)

        :type config_object: str or dict

        :returns: new Config object

        >>> Config(dict(parameters=dict(p1=3, p2=4.6), another_thing=[]))
        Config with elements: another_thing, parameters

        >>> Config("pysystemtrade.sysdata.tests.exampleconfig.yaml")
        Config with elements: parameters, trading_rules

        >>> Config(["pysystemtrade.sysdata.tests.exampleconfig.yaml", dict(parameters=dict(p1=3, p2=4.6), another_thing=[])])
        Config with elements: another_thing, parameters, trading_rules

        """
        setattr(self, "_elements", [])  # will be populated later

        # this will normally be overriden by the base system
        setattr(self, "log", logtoscreen(stage="config"))

        if isinstance(config_object, list):
            # multiple configs
            for config_item in config_object:
                self._create_config_from_item(config_item)
        else:
            self._create_config_from_item(config_object)
Exemplo n.º 3
0
 def __init__(self):
     """
     Data socket base class
     """
     # this will normally be overriden by the base system
     setattr(self, "log", logtoscreen(stage="data"))
Exemplo n.º 4
0
    def __init__(self,
                 stage_list,
                 data,
                 config=None,
                 log=logtoscreen("base_system")):
        """
        Create a system object for doing simulations or live trading

        :param stage_list: A list of stages
        :type stage_list: list of systems.stage.SystemStage (or anything that inherits from it)

        :param data: data for doing simulations
        :type data: sysdata.data.Data (or anything that inherits from that)

        :param config: Optional configuration
        :type config: sysdata.configdata.Config

        :returns: new system object

        >>> from pysystemtrade.systems.stage import SystemStage
        >>> stage=SystemStage()
        >>> from pysystemtrade.sysdata.csvdata import csvFuturesData
        >>> data=csvFuturesData()
        >>> System([stage], data)
        System with stages: unnamed

        """

        if config is None:
            # Default - for very dull systems this is sufficient
            config = Config()

        setattr(self, "data", data)
        setattr(self, "config", config)
        setattr(self, "log", log)

        self.config._system_init(self)
        self.data._system_init(self)

        stage_names = []

        try:
            iter(stage_list)
        except AssertionError:
            raise Exception(
                "You didn't pass a list into this System instance; even just one stage should be System([stage_instance])"
            )

        for stage in stage_list:
            """
            This is where we put the methods to store various stages of the process

            """

            # Stages have names, which are also how we find them in the system
            # attributes
            sub_name = stage.name

            # Each stage has a link back to the parent system
            # This init sets this, and also passes the system logging object
            stage._system_init(self)

            if sub_name in stage_names:
                raise Exception(
                    "You have duplicate subsystems with the name %s. Remove "
                    "one of them, or change a name." % sub_name)

            setattr(self, sub_name, stage)

            stage_names.append(sub_name)

        setattr(self, "_stage_names", stage_names)
        """
        The cache hides all intermediate results

        We call optimal_positions and then that propogates back finding all the
        data we need

        The results are then cached in the object. Should we call
            delete_instrument_data (in base class system) then everything
            related to a particular instrument is removed from these 'nodes'
            except for protected items

        This is very useful in live trading when we don't want to update eg
            cross sectional data every sample
        """

        setattr(self, "cache", systemCache(self))
        self.name = "base_system"  # makes caching work and for general consistency
Exemplo n.º 5
0
    def __init__(
            self,
            data,
            identifier=None,
            parent=None,
            frequency="W",
            date_method="expanding",
            rollyears=20,
            method="bootstrap",
            cleaning=True,
            cost_multiplier=1.0,
            apply_cost_weight=True,
            ann_target_SR=TARGET_ANN_SR,
            equalise_gross=False,
            pool_gross_returns=False,
            use_pooled_costs=False,
            use_pooled_turnover=None,  # not used
            **passed_params):
        """

        Set up optimiser
        :param data: A dict of account curve dataframes, if not pooled data will only have one entry
        :type data: dict

        :param identifier: A dictionary key which refers to the element in data which we're optimising for
        :type identifier: str

        :param parent: The parent object, probably a system stage, which we get the log attribute from
        :type parent: systemStage

        :param frequency: Downsampling frequency. Must be "D", "W" or bigger
        :type frequency: str

        :param date_method: Method to pass to generate_fitting_dates
        :type date_method: str

        :param roll_years: If date_method is "rolling", number of years in window
        :type roll_years: int

        :param method: Method used for fitting, one of 'bootstrap', 'shrinkage', 'one_period'
        :type method: str

        :param cleaning: Do we clean weights so we don't need a warmup period?
        :type cleaning: bool

        :param equalise_gross: Should we equalise expected gross returns so that only costs affect weightings?
        :type equalise_gross: bool

        :param pool_gross_returns: Should we pool gross returns together?
        :type pool_gross_returns: bool

        :param use_pooled_costs: Should we pool costs together?
        :type use_pooled_costs: bool

        :param cost_multiplier: Multiply costs by this number
        :type cost_multiplier: float

        :param apply_cost_weight: Should we adjust our weightings to reflect costs?
        :type apply_cost_weight: bool

        :param *_estimate_params: dicts of **kwargs to pass to moments estimation, and optimisation functions

        :returns: pd.DataFrame of weights
        """

        if parent is None:
            log = logtoscreen("optimiser")
        else:
            log = parent.log

        setattr(self, "log", log)

        # Because interaction of parameters is complex, display warnings
        self.display_warnings(cost_multiplier, equalise_gross,
                              apply_cost_weight, method, **passed_params)

        cleaning = str2Bool(cleaning)
        optimise_params = copy(passed_params)

        # annualisation
        ANN_DICT = dict(D=BUSINESS_DAYS_IN_YEAR,
                        W=WEEKS_IN_YEAR,
                        M=MONTHS_IN_YEAR,
                        Y=1.0)
        annualisation = ANN_DICT.get(frequency, 1.0)

        self.set_up_data(data,
                         frequency=frequency,
                         equalise_gross=equalise_gross,
                         cost_multiplier=cost_multiplier,
                         annualisation=annualisation,
                         ann_target_SR=TARGET_ANN_SR,
                         use_pooled_costs=use_pooled_costs,
                         pool_gross_returns=pool_gross_returns,
                         identifier=identifier)

        # A moments estimator works out the mean, vol, correlation
        # Also stores annualisation factor and target SR (used for shrinkage
        # and equalising)
        moments_estimator = momentsEstimator(optimise_params, annualisation,
                                             ann_target_SR)

        # The optimiser instance will do the optimation once we have the
        # appropriate data
        optimiser = optimiserWithParams(method, optimise_params,
                                        moments_estimator)

        setattr(self, "optimiser", optimiser)
        setattr(self, "frequency", frequency)
        setattr(self, "method", method)
        setattr(self, "equalise_gross", equalise_gross)
        setattr(self, "cost_multiplier", cost_multiplier)
        setattr(self, "annualisation", annualisation)
        setattr(self, "date_method", date_method)
        setattr(self, "rollyears", rollyears)
        setattr(self, "cleaning", cleaning)
        setattr(self, "apply_cost_weight", apply_cost_weight)