예제 #1
0
 def on_bar(self, bar: BarData) -> None:
     bar.datetime = str(bar)
     data = {
         "type": "bar",
         "data": bar._to_dict()
     }
     self.io.emit('bar', data)
예제 #2
0
    def __call__(self, data):
        """
        你必须实现此方法以支持在此层进行中转
        """
        if data.local_symbol not in self.instrument_set:
            return
        if not self.active:
            return

        if isinstance(data, ContractData):
            self.on_contract(data)
        elif isinstance(data, OrderData):
            self.on_order(data)
        elif isinstance(data, TradeData):
            self.on_trade(data)
        elif isinstance(data, AccountData):
            self.on_account(data)
        elif isinstance(data, PositionData):
            self.on_position(data)
        elif data['type'] == "bar":
            self.on_bar(BarData(**data))
        elif data['type'] == "tick":
            self.on_tick(TickData(**data))
        else:
            raise ValueError("unsupported data")
예제 #3
0
    def update_bar(self, xmin, bar: BarData):
        """
        Update 1 minute bar into generator
        """
        xmin_bar = getattr(self, f"min_{xmin}_bar", None)
        if not xmin_bar:
            xmin_bar = BarData(symbol=bar.symbol,
                               exchange=bar.exchange,
                               datetime=bar.datetime,
                               gateway_name=bar.gateway_name,
                               open_price=bar.open_price,
                               high_price=bar.high_price,
                               low_price=bar.low_price)
            setattr(self, f"min_{xmin}_bar", xmin_bar)
        else:
            xmin_bar.high_price = max(xmin_bar.high_price, bar.high_price)
            xmin_bar.low_price = min(xmin_bar.low_price, bar.low_price)

        xmin_bar.close_price = bar.close_price
        xmin_bar.volume += int(bar.volume)

        if not (bar.datetime.minute + 1) % xmin:
            xmin_bar.datetime = xmin_bar.datetime.replace(second=0,
                                                          microsecond=0)
            xmin_bar.interval = xmin
            event = Event(type=EVENT_BAR, data=xmin_bar)
            common_signals.bar_signal.send(event)
            setattr(self, f"min_{xmin}_bar", None)
예제 #4
0
    def update_tick(self, tick: TickData):
        """
        Update new tick data into generator and new_shared time data.
        """
        new_minute = False
        self.last_price = tick.last_price
        self.open_interest = tick.open_interest
        self.volume = tick.volume
        self.molecule = self.molecule + tick.last_price * tick.volume
        self.denominator = self.denominator + tick.volume
        try:
            self.average_price = self.molecule / self.denominator
        except ZeroDivisionError:
            self.average_price = tick.last_price

        if self.last_volume is None:
            self.last_volume = tick.volume
        if self.local_symbol is None:
            self.local_symbol = tick.local_symbol
        if not self.bar:
            new_minute = True
        elif self.bar.datetime.minute != tick.datetime.minute:
            self.bar.datetime = self.bar.datetime.replace(
                second=0, microsecond=0
            )
            self.bar.interval = 1
            event = Event(type=EVENT_BAR, data=self.bar)
            self.rpo.put(event)
            [self.update_bar(x, getattr(self, "min_{}_bar".format(x)), self.bar) for x in self.XMIN]
            new_minute = True
        if new_minute:
            shared = SharedData(last_price=round(self.last_price, 2), datetime=tick.datetime, local_symbol=self.local_symbol,
                                open_interest=self.open_interest, average_price=round(self.average_price, 2),
                                volume=self.volume - self.last_volume, gateway_name=tick.gateway_name)
            self.last_volume = tick.volume
            event = Event(type=EVENT_SHARED, data=shared)
            self.rpo.put(event)
            self.bar = BarData(
                symbol=tick.symbol,
                exchange=tick.exchange,
                datetime=tick.datetime,
                gateway_name=tick.gateway_name,
                open_price=tick.last_price,
                high_price=tick.last_price,
                low_price=tick.last_price,
                close_price=tick.last_price,
            )
        else:
            self.bar.high_price = max(self.bar.high_price, tick.last_price)
            self.bar.low_price = min(self.bar.low_price, tick.last_price)
            self.bar.close_price = tick.last_price
            self.bar.datetime = tick.datetime

        if self.last_tick:
            volume_change = tick.volume - self.last_tick.volume
            self.bar.volume += max(volume_change, 0)
        self.last_tick = tick
예제 #5
0
파일: generator.py 프로젝트: zwb195/ctpbee
    def update_bar(self, xmin, xmin_bar: BarData, bar: BarData):
        """
        Update 1 minute bar into generator
        """
        if not xmin_bar:
            xmin_bar = BarData(symbol=bar.symbol,
                               exchange=bar.exchange,
                               datetime=bar.datetime,
                               gateway_name=bar.gateway_name,
                               open_price=bar.open_price,
                               high_price=bar.high_price,
                               low_price=bar.low_price)
        else:
            xmin_bar.high_price = max(xmin_bar.high_price, bar.high_price)
            xmin_bar.low_price = min(xmin_bar.low_price, bar.low_price)

        xmin_bar.close_price = bar.close_price
        xmin_bar.volume += int(bar.volume)
        if not (bar.datetime.minute + 1) % xmin:
            xmin_bar.datetime = xmin_bar.datetime.replace(second=0,
                                                          microsecond=0)
            xmin_bar.interval = xmin
            event = Event(type=EVENT_BAR, data=xmin_bar)
            self.rpo.put(event)
            xmin_bar = None
예제 #6
0
    def update_tick(self, tick: TickData):
        """
        Update new tick data into generator and new_shared time data.
        """
        new_minute = False
        """ 更新价位 """
        self.last_price = tick.last_price
        self.open_interest = tick.open_interest
        self.volume = tick.volume

        if self.last_volume is None:
            self.last_volume = tick.volume
        if self.local_symbol is None:
            self.local_symbol = tick.local_symbol
        if not self.bar:
            new_minute = True
        elif self.bar.datetime.minute != tick.datetime.minute:
            self.bar.datetime = self.bar.datetime.replace(second=0,
                                                          microsecond=0)
            self.bar.interval = 1
            event = Event(type=EVENT_BAR, data=self.bar)
            common_signals.bar_signal.send(event)
            [self.update_bar(x, self.bar) for x in self.XMIN]
            new_minute = True
        if new_minute:
            self.last_volume = tick.volume
            gateway_name = tick.gateway_name if getattr(
                tick, "gateway_name", None) else "looper"
            self.bar = BarData(
                symbol=tick.symbol,
                exchange=tick.exchange,
                datetime=tick.datetime,
                gateway_name=gateway_name,
                open_price=tick.last_price,
                high_price=tick.last_price,
                low_price=tick.last_price,
                close_price=tick.last_price,
            )
        else:
            self.bar.high_price = max(self.bar.high_price, tick.last_price)
            self.bar.low_price = min(self.bar.low_price, tick.last_price)
            self.bar.close_price = tick.last_price
            self.bar.datetime = tick.datetime

        if self.last_tick:
            """ 更新volume的改变 """
            volume_change = tick.volume - self.last_tick.volume
            self.bar.volume += max(volume_change, 0)
        self.last_tick = tick
예제 #7
0
 def resample(self, tick_data: TickData) -> BarData or None:
     data = []
     for frq, last in self.last_entity.items():
         if last is None:
             self.last_entity[frq] = BarData(
                 datetime=tick_data.datetime,
                 high_price=tick_data.last_price,
                 low_price=tick_data.last_price,
                 close_price=tick_data.last_price,
                 open_price=tick_data.last_price,
                 interval=frq,
                 volume=0,
                 first_volume=tick_data.volume,
                 local_symbol=tick_data.local_symbol,
             )
             self.last_datetime[frq] = tick_data.datetime
         else:
             if frq != 1 and tick_data.datetime.minute % frq == 0 and abs(
                 (tick_data.datetime -
                  self.last_datetime[frq]).seconds) >= 60:
                 temp = deepcopy(last)
                 if self.check_tick(tick_data):
                     temp.high_price = max(temp.high_price,
                                           tick_data.last_price)
                     temp.low_price = min(temp.low_price,
                                          tick_data.last_price)
                     temp.close_price = tick_data.last_price
                     temp.volume += max(
                         tick_data.volume - temp.first_volume, 0)
                 self.last_entity[frq] = BarData(
                     datetime=tick_data.datetime,
                     high_price=tick_data.last_price,
                     low_price=tick_data.last_price,
                     close_price=tick_data.last_price,
                     open_price=tick_data.last_price,
                     interval=frq,
                     volume=tick_data.volume - temp.first_volume,
                     first_volume=tick_data.volume,
                     local_symbol=tick_data.local_symbol)
                 self.last_datetime[frq] = tick_data.datetime
                 data.append(temp)
             elif frq != 1:
                 self.last_entity[frq].high_price = max(
                     self.last_entity[frq].high_price, tick_data.last_price)
                 self.last_entity[frq].low_price = min(
                     self.last_entity[frq].low_price, tick_data.last_price)
                 self.last_entity[frq].close_price = tick_data.last_price
                 self.last_entity[frq].volume += max(
                     tick_data.volume - self.last_entity[frq].first_volume,
                     0)
                 self.last_entity[frq].first_volume = tick_data.volume
             # 处理一分钟的k线
             if frq == 1 and tick_data.datetime.second == 0 and \
                     abs((tick_data.datetime - self.last_datetime[frq]).seconds) > 10:
                 temp = deepcopy(last)
                 if self.check_tick(tick_data):
                     temp.high_price = max(temp.high_price,
                                           tick_data.last_price)
                     temp.low_price = min(temp.low_price,
                                          tick_data.last_price)
                     temp.close_price = tick_data.last_price
                     temp.volume += max(
                         tick_data.volume - temp.first_volume, 0)
                 self.last_entity[frq] = BarData(
                     datetime=tick_data.datetime,
                     high_price=tick_data.last_price,
                     low_price=tick_data.last_price,
                     close_price=tick_data.last_price,
                     open_price=tick_data.last_price,
                     interval=frq,
                     volume=tick_data.volume - temp.first_volume,
                     first_volume=tick_data.volume,
                     local_symbol=tick_data.local_symbol)
                 self.last_datetime[frq] = tick_data.datetime
                 data.append(temp)
             elif frq == 1:
                 self.last_entity[frq].high_price = max(
                     self.last_entity[frq].high_price, tick_data.last_price)
                 self.last_entity[frq].low_price = min(
                     self.last_entity[frq].low_price, tick_data.last_price)
                 self.last_entity[frq].close_price = tick_data.last_price
                 self.last_entity[frq].volume += max(
                     tick_data.volume - self.last_entity[frq].first_volume,
                     0)
                 self.last_entity[frq].first_volume = tick_data.volume
     return data
예제 #8
0
    def resample(self, tick_data: TickData) -> BarData or None:
        data = []
        for frq, last in self.last_entity.items():
            if last is None:
                self.last_entity[frq] = BarData(
                    datetime=tick_data.datetime,
                    high_price=tick_data.last_price,
                    low_price=tick_data.last_price,
                    close_price=tick_data.last_price,
                    open_price=tick_data.last_price,
                    interval=frq,
                    volume=0,
                    first_volume=tick_data.volume,
                    local_symbol=tick_data.local_symbol,
                )
                self.last_datetime[frq] = tick_data.datetime
            else:
                if self.lock_free[frq] is False:
                    if tick_data.datetime.hour == self.last_entity[frq].datetime.hour \
                            and tick_data.datetime.minute == self.last_entity[frq].datetime.minute \
                            and tick_data.datetime.second == self.last_entity[frq].datetime.second:
                        self.lock_free[frq] = True
                if frq != 1 and tick_data.datetime.minute % frq == 0 and abs(
                        (tick_data.datetime - self.last_datetime[frq]).seconds) >= 60 \
                        and self.lock_free[frq] is True:
                    temp = deepcopy(last)
                    check, tim = self.check_tick(tick_data)
                    if check is True:
                        temp.high_price = max(temp.high_price,
                                              tick_data.last_price)
                        temp.low_price = min(temp.low_price,
                                             tick_data.last_price)
                        temp.close_price = tick_data.last_price
                        temp.volume += max(
                            tick_data.volume - temp.first_volume, 0)
                        self.last_entity[frq] = BarData(
                            datetime=tim,
                            high_price=tick_data.last_price,
                            low_price=tick_data.last_price,
                            close_price=tick_data.last_price,
                            open_price=tick_data.last_price,
                            interval=frq,
                            volume=0,
                            first_volume=tick_data.volume,
                            local_symbol=tick_data.local_symbol)
                        self.lock_free[frq] = False
                        self.last_datetime[frq] = tim
                    else:
                        self.last_entity[frq] = BarData(
                            datetime=tick_data.datetime,
                            high_price=tick_data.last_price,
                            low_price=tick_data.last_price,
                            close_price=tick_data.last_price,
                            open_price=tick_data.last_price,
                            interval=frq,
                            volume=tick_data.volume - temp.first_volume,
                            first_volume=tick_data.volume,
                            local_symbol=tick_data.local_symbol)
                        self.last_datetime[frq] = tick_data.datetime
                    data.append(temp)

                elif frq != 1 and self.lock_free[frq] is True:
                    self.last_entity[frq].high_price = max(
                        self.last_entity[frq].high_price, tick_data.last_price)
                    self.last_entity[frq].low_price = min(
                        self.last_entity[frq].low_price, tick_data.last_price)
                    self.last_entity[frq].close_price = tick_data.last_price
                    self.last_entity[frq].volume += max(
                        tick_data.volume - self.last_entity[frq].first_volume,
                        0)
                    self.last_entity[frq].first_volume = tick_data.volume
                """
                处理一分钟的k线数据
                """
                if frq == 1 and tick_data.datetime.second == 0 and \
                        abs((tick_data.datetime - self.last_datetime[frq]).seconds) > 10 \
                        and self.lock_free[frq] is True:
                    temp = deepcopy(last)
                    check, tim = self.check_tick(tick_data)
                    if check is True:
                        """ 特殊时间需要特殊有处理 """
                        temp.high_price = max(temp.high_price,
                                              tick_data.last_price)
                        temp.low_price = min(temp.low_price,
                                             tick_data.last_price)
                        temp.close_price = tick_data.last_price
                        temp.volume += max(
                            tick_data.volume - temp.first_volume, 0)
                        self.last_entity[frq] = BarData(
                            datetime=tim,
                            high_price=tick_data.last_price,
                            low_price=tick_data.last_price,
                            close_price=tick_data.last_price,
                            open_price=tick_data.last_price,
                            interval=frq,
                            volume=0,
                            first_volume=tick_data.volume,
                            local_symbol=tick_data.local_symbol)
                        self.lock_free[frq] = False
                        self.last_datetime[frq] = tim
                    else:
                        self.last_entity[frq] = BarData(
                            datetime=tick_data.datetime,
                            high_price=tick_data.last_price,
                            low_price=tick_data.last_price,
                            close_price=tick_data.last_price,
                            open_price=tick_data.last_price,
                            interval=frq,
                            volume=tick_data.volume - temp.first_volume,
                            first_volume=tick_data.volume,
                            local_symbol=tick_data.local_symbol)
                        self.last_datetime[frq] = tick_data.datetime
                    data.append(temp)
                elif frq == 1 and self.lock_free[frq]:
                    self.last_entity[frq].high_price = max(
                        self.last_entity[frq].high_price, tick_data.last_price)
                    self.last_entity[frq].low_price = min(
                        self.last_entity[frq].low_price, tick_data.last_price)
                    self.last_entity[frq].close_price = tick_data.last_price
                    """ 累积成交量 """
                    self.last_entity[frq].volume += max(
                        tick_data.volume - self.last_entity[frq].first_volume,
                        0)
                    self.last_entity[frq].first_volume = tick_data.volume

        return data
예제 #9
0
    def __call__(self, *args, **kwargs):
        """ 回测周期 """
        entity = args[0]
        # 日期不相等时, 更新前日结算价格
        if self.account.date is None:
            self.account.date = self.date
        if self.date is None:
            self.date = entity.datetime.date()
        if not self.auth_time(entity.datetime):
            return
        self.data_type = entity.type
        # 回测的时候自动更新策略的日期
        try:
            seconds = (entity.datetime - self.datetime).seconds
            if seconds >= 60 * 60 * 4 and (entity.datetime.hour >= 21 or (
                (14 <= self.datetime.hour <= 15)
                    and entity.datetime.date() != self.datetime.date())):
                self.account.settle(entity.datetime.date())
                # 针对于账户的实现 我们需要将昨仓转换为今仓
                self.app.recorder.position_manager.covert_to_yesterday_holding(
                )
                for local_symbol, price in self.price_mapping.items():
                    self.pre_close_price[local_symbol] = price
                #  结算完触发初始化函数
                self.on_event(EVENT_INIT_FINISHED, True)
        except KeyError:
            pass
        except AttributeError:
            pass
        self.data_entity = entity
        self.change_month_record["".join(
            filter(str.isalpha,
                   entity.local_symbol.split(".")[0]))] = entity
        # 维护一个最新的价格
        self.price_mapping[self.data_entity.local_symbol] = self.data_entity.close_price if entity.type == "bar" \
            else self.data_entity.last_price
        if self.pre_close_price.get(self.data_entity.local_symbol) is None:
            self.pre_close_price[
                self.data_entity.
                local_symbol] = self.data_entity.last_price if entity.type == "tick" else self.data_entity.close_price
        self.datetime = entity.datetime
        self.match_deal()

        if entity.type == "tick":
            self.account.position_manager.update_tick(
                self.data_entity,
                self.pre_close_price[self.data_entity.local_symbol])
            self.app.recorder.position_manager.update_tick(
                self.data_entity,
                self.pre_close_price[self.data_entity.local_symbol])
            self.on_event(EVENT_TICK, TickData(**entity))

        if entity.type == "bar":
            self.account.position_manager.update_bar(
                self.data_entity,
                self.pre_close_price[self.data_entity.local_symbol])
            self.app.recorder.position_manager.update_bar(
                self.data_entity,
                self.pre_close_price[self.data_entity.local_symbol])
            self.on_event(EVENT_BAR, BarData(**entity))

        if entity.datetime.hour >= 21:
            """if hour > 21, switch to next trade day"""
            index = trade_dates.index(str(entity.datetime.date()))
            self.date = datetime.strptime(trade_dates[index + 1],
                                          "%Y-%m-%d").date()
        else:
            if str(entity.datetime.date()) not in trade_dates:
                last_day = entity.datetime + timedelta(days=-1)
                self.date = datetime.strptime(
                    trade_dates[trade_dates.index(str(last_day.date())) + 1],
                    "%Y-%m-%d").date()
            else:
                self.date = entity.datetime.date()
        # 穿过接口日期检查
        self.account.via_aisle()