Esempio n. 1
0
 def run(self, alert_manager=None, publish=False, show_progress=False):
     if self.mode == MODE.LIVE:
         self.live_run(alert_manager, publish)  # no progress bar for live
     elif self.mode == MODE.BACKTEST:
         self.back_test_run(alert_manager, publish, show_progress)
     else:
         raise StateMachineError(msg="undefined mode")
Esempio n. 2
0
    def live_run(self, alert_manager=None, publish_packets=False):
        '''
            The entry point for a live run.
        '''
        if self.mode != MODE.LIVE:
            raise StateMachineError(msg="mode must be live")

        if not self.context.is_initialized():
            raise InitializationError(msg="context is not "
                                      "properly initialized")

        if not isinstance(self.context.clock, RealtimeClock):
            raise ValidationError(msg="clock must be real-time clock")

        # reset the clock at the start of the run, this also aligns
        # ticks to the nearest rounded bar depending on the frequency
        self._reset_clock(self.context.clock.emit_frequency)

        # initialize the coroutines
        clock_coro = self.context.clock.tick()
        algo_coro = self._run_live(alert_manager, publish_packets)

        try:
            tasks = asyncio.gather(clock_coro,
                                   algo_coro,
                                   return_exceptions=False)
            self._loop.run_until_complete(tasks)
        except BaseException as e:
            # TODO: do a proper exception handling here
            print("exception {}".format(e))
            tasks.cancel()
            raise e
        finally:
            self._loop.close()
Esempio n. 3
0
 def shutdown(self, *args, **kwargs):
     try:
         self.fsm_stop()
         self.log_warning("algorithm stopped.")
     except MachineError:
         # this should never fail.
         msg = f"State Machine Error ({self.state}): attempt to stop."
         raise StateMachineError(msg=msg)
Esempio n. 4
0
 def pause(self, *args, **kwargs):
     try:
         self.fsm_pause()
         msg = "algorithm paused. No further processing till resumed."
         self.log_warning(msg)
     except MachineError:
         msg = f"State Machine Error ({self.state}): attempt to pause."
         raise StateMachineError(msg=msg)
Esempio n. 5
0
    def state(self, to_state):
        if to_state not in self._transition_dict[self._current_state]:
            strmsg = f"Illegal state change from {self._current_state}\
                        to {to_state}"

            raise StateMachineError(msg=strmsg)

        self._current_state = to_state
Esempio n. 6
0
    def before_trading_start(self, timestamp):
        '''
            Called at the start of the session.
        '''
        try:
            self.fsm_before_trading_start()
        except MachineError:
            msg = f"State Machine Error ({self.state}): in before_trading_start"
            raise StateMachineError(msg=msg)

        self._before_trading_start(self.context, self.context.data_portal)

        # call the handle data state update here.
        if self.mode != MODE.LIVE:
            try:
                self.fsm_handle_data()
            except MachineError:
                msg = f"State Machine Error ({self.state}): in handle_data"
                raise StateMachineError(msg=msg)
Esempio n. 7
0
    def heartbeat(self, timestamp):
        '''
            Called when we are not in a session.
        '''
        try:
            self.fsm_heartbeat()
        except MachineError:
            msg = f"State Machine Error ({self.state}): in heartbeat"
            raise StateMachineError(msg=msg)

        self._heartbeat(self.context)
Esempio n. 8
0
    def analyze(self, timestamp):
        '''
            Called at the end of the algo run.
        '''
        try:
            self.fsm_analyze()
        except MachineError:
            msg = f"State Machine Error ({self.state}): in analyze"
            raise StateMachineError(msg=msg)

        self._analyze(self.context)
Esempio n. 9
0
    def after_trading_hours(self, timestamp):
        '''
            Called at the end of the session.
        '''
        try:
            self.fsm_after_trading_hours()
        except MachineError:
            msg = f"State Machine Error ({self.state}): in after_trading_hours"
            raise StateMachineError(msg=msg)

        self._after_trading_hours(self.context, self.context.data_portal)
Esempio n. 10
0
    def initialize(self, timestamp):
        '''
            Called at the start of the algo. Or at every resume command.
        '''
        try:
            self.fsm_initialize()
        except MachineError:
            msg = f"State Machine Error ({self.state}): in initialize"
            raise StateMachineError(msg=msg)

        self._initialize(self.context)
Esempio n. 11
0
    def _back_test_generator(self, alert_manager=None):
        '''
            The entry point for backtest run. This generator yields
            the current day performance.
        '''
        if self.mode != MODE.BACKTEST:
            raise StateMachineError(msg="mode must be back-test")

        if not self.context.is_initialized():
            raise InitializationError(msg="context is not "
                                      "properly initialized")

        if not isinstance(self.context.clock, SimulationClock):
            raise ValidationError(msg="clock must be simulation clock")

        self._make_broker_dispatch()  # only useful for backtest

        for t, bar in self.context.clock:
            try:
                ts = pd.Timestamp(t,
                                  unit='ns',
                                  tz=self.context.trading_calendar.tz)

                if bar == BARS.ALGO_START:
                    self.context.set_up(timestamp=ts)

                self.context.set_timestamp(ts)
                self._BROKER_FUNC_DISPATCH.get(bar, self._bar_noop)(ts)

                if bar == BARS.TRADING_BAR:
                    #self.context.BAR_update(ts)
                    pass

                if bar == BARS.AFTER_TRADING_HOURS:
                    #self.context.BAR_update(ts)
                    self.context.EOD_update(ts)
                    perf = self.context.performance
                    perf['timestamp'] = str(self.context.timestamp)
                    yield perf

                self._USER_FUNC_DISPATCH.get(bar, self._bar_noop)(ts)

            except BlueShiftException as e:
                if not alert_manager:
                    raise e
                else:
                    timestamp = self.context.timestamp
                    alert_manager.handle_error(e,
                                               'algorithm',
                                               mode=self.mode,
                                               timestamp=timestamp)
                    continue
Esempio n. 12
0
    def set_broker(self, name, *args, **kwargs):
        '''
            Change the broker in run time. This is useful to modify
            the broker api (including execution logic if any) or the
            capital. This will NOT change the clock, and we do not 
            want that either.
        '''
        if not self.is_INITIALIZED() or not self.is_HEARTBEAT():
            msg = "cannot set broker in state ({self.state})"
            raise StateMachineError(msg=msg)

        broker = get_broker(name, *args, **kwargs)

        # we cannot switch from backtest to live or reverse
        if type(self.context.clock) != type(broker.clock):
            msg = "cannot switch from backtest to live or reverse"
            raise StateMachineError(msg=msg)

        # we should not attempt to change the clock!
        self.context.reset(api=broker.broker,
                           auth=broker.auth,
                           asset_finder=broker.asset_finder,
                           data_portal=broker.data_portal)
Esempio n. 13
0
 def resume(self, *args, **kwargs):
     '''
         Resuming an algo trigger state changes starting with a call
         to initialize.
     '''
     try:
         self.fsm_resume()  # PAUSED ==> STARTUP
         # TODO: this is risky, there is a change that the queue
         # may be None within the tick coroutine in clock possibly?
         self._reset_clock(self.context.clock.emit_frequency)
         self.log_warning("algorithm resumed.")
     except MachineError:
         msg = f"State Machine Error ({self.state}): attempt to resume."
         raise StateMachineError(msg=msg)
Esempio n. 14
0
    def handle_data(self, timestamp):
        '''
            Called at the start of each trading bar. We call the state
            machine function only for live mode here, and club with 
            before trading start for backtest mode. This a bit hacky but
            speeds things up.
        '''
        if self.mode == MODE.LIVE:
            try:
                self.fsm_handle_data()
            except MachineError:
                msg = f"State Machine Error ({self.state}): in handle_data"
                raise StateMachineError(msg=msg)

        self._handle_data(self.context, self.context.data_portal)