Exemple #1
0
    def update_account(self, dt, balance):
        """
        更新资金曲线
        :param dt:
        :param balance: 账号级别,直接使用账号得的balance;
        :return:
        """
        tick = TickData(gateway_name='Fund',
                        symbol=self.symbol,
                        exchange=Exchange.LOCAL,
                        datetime=dt)
        tick.last_price = balance
        tick.volume = 1
        tick.ask_price_1 = balance
        tick.ask_volume_1 = 1
        tick.bid_price_1 = balance
        tick.bid_volume_1 = 1
        tick.date = tick.datetime.strftime('%Y-%m-%d')
        tick.time = tick.datetime.strftime('%H:%M:%S')
        tick.trading_day = get_trading_date(dt)
        tick.open_interest = balance

        if self.inited:
            self.kline.on_tick(tick)

        # 如果是从账号更新,无法更新持仓盈亏
        self.closed_profit = balance
        self.holding_profit = 0
Exemple #2
0
    def update_strategy(self, dt, closed_pnl=0, hold_pnl=0):
        """
        更新资金曲线
        :param dt:
        :param closed_pnl: 策略提供的平仓盈亏
        :param hold_pnl: 策略提供的持仓盈亏
        :return:
        """
        # 获取当前bar的平仓权益
        open_interest = 0
        if len(self.kline.line_bar) > 0:
            open_interest = self.kline.line_bar[-1].open_interest

        if closed_pnl != 0:
            self.write_log(u'策略平仓收益:{}->{}'.format(open_interest,
                                                   open_interest + closed_pnl))
            open_interest += closed_pnl

        tick = TickData(gateway_name='Fund',
                        symbol=self.symbol,
                        exchange=Exchange.LOCAL,
                        datetime=dt)

        tick.last_price = open_interest + hold_pnl
        tick.volume = 1
        tick.ask_price1 = open_interest + hold_pnl
        tick.ask_volume1 = 1
        tick.bid_price1 = open_interest + hold_pnl
        tick.bid_volume1 = 1
        tick.datetime = dt
        tick.open_interest = open_interest
        tick.date = tick.datetime.strftime('%Y-%m-%d')
        tick.time = tick.datetime.strftime('%H:%M:%S')
        tick.trading_day = get_trading_date(dt)

        if self.inited:
            self.kline.on_tick(tick)

        self.closed_profit = open_interest
        self.holding_profit = hold_pnl
    def onRtnDepthMarketData(self, data: dict):
        """
        Callback of tick data update.
        """
        symbol = data["InstrumentID"]
        exchange = symbol_exchange_map.get(symbol, "")
        if not exchange:
            return

        timestamp = f"{data['ActionDay']} {data['UpdateTime']}.{int(data['UpdateMillisec']/100)}"
        dt = datetime.strptime(timestamp, "%Y%m%d %H:%M:%S.%f")

        # 不处理开盘前的tick数据
        if dt.hour in [8, 20] and dt.minute < 59:
            return
        if exchange is Exchange.CFFEX and dt.hour == 9 and dt.minute < 14:
            return

        tick = TickData(symbol=symbol,
                        exchange=exchange,
                        datetime=dt,
                        date=dt.strftime('%Y-%m-%d'),
                        time=dt.strftime('%H:%M:%S.%f'),
                        trading_day=get_trading_date(dt),
                        name=symbol_name_map[symbol],
                        volume=data["Volume"],
                        open_interest=data["OpenInterest"],
                        last_price=data["LastPrice"],
                        limit_up=data["UpperLimitPrice"],
                        limit_down=data["LowerLimitPrice"],
                        open_price=adjust_price(data["OpenPrice"]),
                        high_price=adjust_price(data["HighestPrice"]),
                        low_price=adjust_price(data["LowestPrice"]),
                        pre_close=adjust_price(data["PreClosePrice"]),
                        bid_price_1=adjust_price(data["BidPrice1"]),
                        ask_price_1=adjust_price(data["AskPrice1"]),
                        bid_volume_1=data["BidVolume1"],
                        ask_volume_1=data["AskVolume1"],
                        gateway_name=self.gateway_name)

        if data["BidVolume2"] or data["AskVolume2"]:
            tick.bid_price_2 = adjust_price(data["BidPrice2"])
            tick.bid_price_3 = adjust_price(data["BidPrice3"])
            tick.bid_price_4 = adjust_price(data["BidPrice4"])
            tick.bid_price_5 = adjust_price(data["BidPrice5"])

            tick.ask_price_2 = adjust_price(data["AskPrice2"])
            tick.ask_price_3 = adjust_price(data["AskPrice3"])
            tick.ask_price_4 = adjust_price(data["AskPrice4"])
            tick.ask_price_5 = adjust_price(data["AskPrice5"])

            tick.bid_volume_2 = adjust_price(data["BidVolume2"])
            tick.bid_volume_3 = adjust_price(data["BidVolume3"])
            tick.bid_volume_4 = adjust_price(data["BidVolume4"])
            tick.bid_volume_5 = adjust_price(data["BidVolume5"])

            tick.ask_volume_2 = adjust_price(data["AskVolume2"])
            tick.ask_volume_3 = adjust_price(data["AskVolume3"])
            tick.ask_volume_4 = adjust_price(data["AskVolume4"])
            tick.ask_volume_5 = adjust_price(data["AskVolume5"])

        self.gateway.on_tick(tick)
Exemple #4
0
    def get_history_transaction_data(self, symbol, date, cache_folder=None):
        """获取当某一交易日的历史成交记录"""
        ret_datas = []
        if isinstance(date, datetime):
            date = date.strftime('%Y%m%d')
        if isinstance(date, str):
            date = int(date)

        self.connect()

        cache_symbol = symbol
        cache_date = str(date)

        max_data_size = sys.maxsize
        symbol = symbol.upper()
        if '99' in symbol:
            # 查询的是指数合约
            symbol = symbol.replace('99', 'L9')
            tdx_index_symbol = symbol
        else:
            # 查询的是普通合约
            tdx_index_symbol = get_underlying_symbol(symbol).upper() + 'L9'
        q_size = QSIZE * 5
        # 每秒 2个, 10小时
        max_data_size = 1000000

        # 优先从缓存加载
        if cache_folder:
            buffer_data = self.load_cache(cache_folder, cache_symbol,
                                          cache_date)
            if buffer_data:
                self.write_log(u'使用缓存文件')
                return True, buffer_data

        self.write_log(u'开始下载{} 历史{}分笔数据'.format(date, symbol))
        cur_trading_date = get_trading_date()
        if date == int(cur_trading_date.replace('-', '')):
            return self.get_transaction_data(symbol)
        try:
            _datas = []
            _pos = 0

            while (True):
                _res = self.api.get_history_transaction_data(
                    market=self.symbol_market_dict.get(tdx_index_symbol, 0),
                    date=date,
                    code=symbol,
                    start=_pos,
                    count=q_size)
                if _res is not None:
                    for d in _res:
                        dt = d.pop('date')
                        # 星期1~星期6
                        if dt.hour >= 20 and 1 < dt.isoweekday() <= 6:
                            dt = dt - timedelta(days=1)
                            d.update({'datetime': dt})
                        elif dt.hour >= 20 and dt.isoweekday() == 1:
                            # 星期一取得20点后数据
                            dt = dt - timedelta(days=3)
                            d.update({'datetime': dt})
                        elif dt.hour < 8 and dt.isoweekday() == 1:
                            # 星期一取得8点前数据
                            dt = dt - timedelta(days=3)
                            d.update({'datetime': dt})
                        elif dt.hour >= 20 and dt.isoweekday() == 7:
                            # 星期天取得20点后数据,肯定是星期五夜盘
                            dt = dt - timedelta(days=2)
                            d.update({'datetime': dt})
                        elif dt.isoweekday() == 7:
                            # 星期日取得其他时间,必然是 星期六凌晨的数据
                            dt = dt - timedelta(days=1)
                            d.update({'datetime': dt})
                        else:
                            d.update({'datetime': dt})
                        # 接口有bug,返回价格*1000,所以要除以1000
                        d.update({'price': d.get('price', 0) / 1000})
                    _datas = sorted(_res, key=lambda s: s['datetime']) + _datas
                _pos += min(q_size, len(_res))

                if _res is not None and len(_res) > 0:
                    self.write_log(u'分段取分笔数据:{} ~{}, {}条,累计:{}条'.format(
                        _res[0]['datetime'], _res[-1]['datetime'], len(_res),
                        _pos))
                else:
                    break

                if len(_datas) >= max_data_size:
                    break

            if len(_datas) == 0:
                self.write_error(u'{}分笔成交数据获取为空'.format(date))
                return False, _datas

            # 缓存文件
            if cache_folder:
                self.save_cache(cache_folder, cache_symbol, cache_date, _datas)

            return True, _datas

        except Exception as ex:
            self.write_error(
                'exception in get_transaction_data:{},{},{}'.format(
                    symbol, str(ex), traceback.format_exc()))
            self.write_error(u'当前异常服务器信息:{}'.format(self.best_ip))
            self.write_log(u'重置连接')
            self.api = None
            self.connect(is_reconnect=True)
            return False, ret_datas
Exemple #5
0
    def load(self):
        """
        从本地csv文件恢复k线数据
        :return:
        """
        self.kline_file = str(
            get_folder_path('data').joinpath('fund_{}.csv'.format(
                self.kline_name)))

        # 如果数据文件存在,则加载数据
        if os.path.exists(self.kline_file):
            self.write_log(u'加载{}数据'.format(self.kline_name))
            df = pd.read_csv(self.kline_file)
            dt_now = datetime.now()
            df = df.set_index(pd.DatetimeIndex(df['datetime']))
            for dt, bar_data in df.iterrows():
                bar = BarData()

                bar.symbol = self.symbol
                bar.datetime = dt
                bar.open_price = float(bar_data['open'])
                bar.close_price = float(bar_data['close'])
                bar.high_price = float(bar_data['high'])
                bar.low_price = float(bar_data['low'])
                bar.date = dt.strftime('%Y-%m-%d')
                str_td = str(bar_data.get('trading_date', ''))
                if len(str_td) == 8:
                    bar.trading_day = str_td[0:4] + '-' + str_td[
                        4:6] + '-' + str_td[6:8]
                elif len(str_td) == 0:
                    bar.trading_day = bar.date
                else:
                    bar.trading_day = get_trading_date(dt)
                bar.time = dt.strftime('%H:%M:%S')
                bar.open_interest = float(bar_data.get('open_interest', 0))

                if self.use_renko:
                    self.kline.add_bar(bar)
                else:
                    # bar得时间,与当前时间相隔超过一个小时,加入完整得bar
                    if (dt_now - dt).total_seconds() > 60 * 60:
                        self.kline.add_bar(bar,
                                           bar_is_completed=True,
                                           bar_freq=60)
                    # 可能是最后一根bar
                    else:
                        self.write_log(u'更新最后一根Bar:{},now:{}'.format(
                            dt, dt_now))
                        self.kline.add_bar(bar,
                                           bar_is_completed=False,
                                           bar_freq=dt.minute)
        else:
            self.write_log(u'当前没有资金历史K线文件:{}'.format(self.kline_file))

        self.inited = True

        # 设置 kline的输出文件
        self.kline.export_filename = self.kline_file
        self.kline.export_fields = [{
            'name': 'datetime',
            'source': 'bar',
            'attr': 'datetime',
            'type_': 'datetime'
        }, {
            'name': 'open',
            'source': 'bar',
            'attr': 'open_price',
            'type_': 'float'
        }, {
            'name': 'high',
            'source': 'bar',
            'attr': 'high_price',
            'type_': 'float'
        }, {
            'name': 'low',
            'source': 'bar',
            'attr': 'low_price',
            'type_': 'float'
        }, {
            'name': 'close',
            'source': 'bar',
            'attr': 'close_price',
            'type_': 'float'
        }, {
            'name': 'turnover',
            'source': 'bar',
            'attr': 'turnover',
            'type_': 'float'
        }, {
            'name': 'volume',
            'source': 'bar',
            'attr': 'volume',
            'type_': 'float'
        }, {
            'name': 'open_interest',
            'source': 'bar',
            'attr': 'open_interest',
            'type_': 'float'
        }]