Exemplo n.º 1
0
class QAStrategyCTABase():
    def __init__(self, code='rb1905', frequence='1min', strategy_id='QA_STRATEGY', risk_check_gap=1, portfolio='default',
                 start='2019-01-01', end='2019-10-21', init_cash=1000000, send_wx=False,
                 data_host=eventmq_ip, data_port=eventmq_port, data_user=eventmq_username, data_password=eventmq_password,
                 trade_host=eventmq_ip, trade_port=eventmq_port, trade_user=eventmq_username, trade_password=eventmq_password,
                 taskid=None, mongo_ip=mongo_ip, model= 'py'):
        """
        code 可以传入单个标的 也可以传入一组标的(list)
        会自动基于code来判断是什么市场

        TODO: 支持多个市场同时存在




        """
        self.trade_host = trade_host

        self.code = code
        self.frequence = frequence
        self.strategy_id = strategy_id

        self.portfolio = portfolio

        self.data_host = data_host
        self.data_port = data_port
        self.data_user = data_user
        self.data_password = data_password
        self.trade_host = trade_host
        self.trade_port = trade_port
        self.trade_user = trade_user
        self.trade_password = trade_password

        self.start = start
        self.end = end
        self.init_cash = init_cash
        self.taskid = taskid

        self.running_time = ''

        self.market_preset = QA.QAARP.MARKET_PRESET()
        self._market_data = []
        self.risk_check_gap = risk_check_gap
        self.latest_price = {}

        self.isupdate = False
        self.model = model
        self.new_data = {}
        self._systemvar = {}
        self._signal = []
        self.send_wx = send_wx
        if isinstance(self.code, str):

            self.last_order_towards = {self.code: {'BUY': '', 'SELL': ''}}
        else:
            self.last_order_towards = dict(zip(self.code, [{'BUY': '', 'SELL': ''} for i in range(len(self.code))]))
        self.dt = ''
        if isinstance(self.code, str):
            self.market_type = MARKET_TYPE.FUTURE_CN if re.search(
                r'[a-zA-z]+', self.code) else MARKET_TYPE.STOCK_CN
        else:
            self.market_type = MARKET_TYPE.FUTURE_CN if re.search(
                r'[a-zA-z]+', self.code[0]) else MARKET_TYPE.STOCK_CN

        self.bar_order = {'BUY_OPEN': 0, 'SELL_OPEN': 0,
                          'BUY_CLOSE': 0, 'SELL_CLOSE': 0}

        self._num_cached = 120
        self._cached_data = []
        self.user_init()

    @property
    def bar_id(self):
        return len(self._market_data)

    def _debug_sim(self):

        self.running_mode = 'sim'

        if self.frequence.endswith('min'):

            if isinstance(self.code, str):
                self._old_data = QA.QA_fetch_get_future_min('tdx', self.code.upper(), QA.QA_util_get_last_day(
                    QA.QA_util_get_real_date(str(datetime.date.today()))), str(datetime.datetime.now()), self.frequence)[:-1].set_index(['datetime', 'code'])
                self._old_data = self._old_data.assign(volume=self._old_data.trade).loc[:, [
                    'open', 'high', 'low', 'close', 'volume']]
            else:

                self._old_data = pd.concat([QA.QA_fetch_get_future_min('tdx', item.upper(), QA.QA_util_get_last_day(
                    QA.QA_util_get_real_date(str(datetime.date.today()))), str(datetime.datetime.now()), self.frequence)[:-1].set_index(['datetime', 'code']) for item in self.code], sort=False)
                self._old_data = self._old_data.assign(volume=self._old_data.trade).loc[:, [
                    'open', 'high', 'low', 'close', 'volume']]
        else:
            self._old_data = pd.DataFrame()

        self.database = pymongo.MongoClient(mongo_ip).QAREALTIME

        self.client = self.database.account
        self.subscriber_client = self.database.subscribe

        self.acc = QIFI_Account(
            username=self.strategy_id, password=self.strategy_id, trade_host=mongo_ip, init_cash=self.init_cash)
        self.acc.initial()

        self.pub = publisher_routing(exchange='QAORDER_ROUTER', host=self.trade_host,
                                     port=self.trade_port, user=self.trade_user, password=self.trade_password)
        if isinstance(self.code, str):
            self.subscribe_data(self.code.lower(), self.frequence, self.data_host,
                                self.data_port, self.data_user, self.data_password, self.model)
        else:
            self.subscribe_multi(self.code, self.frequence, self.data_host,
                                self.data_port, self.data_user, self.data_password, self.model)
        print('start sim')
        self.database.strategy_schedule.job_control.update(
            {'strategy_id': self.strategy_id},
            {'strategy_id': self.strategy_id, 'taskid': self.taskid,
             'filepath': os.path.abspath(__file__), 'status': 200}, upsert=True)

    def debug_sim(self):
        self._debug_sim()
        threading.Thread(target=self.sub.start, daemon=True).start()

    def run_sim(self):
        self._debug_sim()

        self.sub.start()

    def run_backtest(self):
        self.debug()
        self.acc.save()

        risk = QA_Risk(self.acc)
        risk.save()

        try:
            """add rank flow if exist

            QARank是我们内部用于评价策略ELO的库 此处并不影响正常使用
            """
            from QARank import QA_Rank
            QA_Rank(self.acc).send()
        except:
            pass


    def user_init(self):
        """
        用户自定义的init过程
        """
        pass

    def debug(self):
        self.running_mode = 'backtest'
        self.database = pymongo.MongoClient(mongo_ip).QUANTAXIS
        user = QA_User(username="******", password='******')
        port = user.new_portfolio(self.portfolio)
        self.acc = port.new_accountpro(
            account_cookie=self.strategy_id, init_cash=self.init_cash, market_type=self.market_type)
        self.positions = self.acc.get_position(self.code)

        print(self.acc)

        print(self.acc.market_type)
        data = QA.QA_quotation(self.code.upper(), self.start, self.end, source=QA.DATASOURCE.MONGO,
                               frequence=self.frequence, market=self.market_type, output=QA.OUTPUT_FORMAT.DATASTRUCT)



        data.data.apply(self.x1, axis=1)

    def x1(self,item):
        # print(data)
        self.latest_price[item.name[1]] = item['close']
        if str(item.name[0])[0:10] != str(self.running_time)[0:10]:
            self.on_dailyclose()
            self.on_dailyopen()
            if self.market_type == QA.MARKET_TYPE.STOCK_CN:
                print('backtest: Settle!')
                self.acc.settle()
        self._on_1min_bar()
        self._market_data.append(item)
        self.running_time = str(item.name[0])
        self.on_bar(item)

    def debug_t0(self):
        self.running_mode = 'backtest'
        self.database = pymongo.MongoClient(mongo_ip).QUANTAXIS
        user = QA_User(username="******", password='******')
        port = user.new_portfolio(self.portfolio)
        self.acc = port.new_accountpro(
            account_cookie=self.strategy_id, init_cash=self.init_cash, init_hold={
                self.code: 100000},
            market_type=self.market_type, running_environment=RUNNING_ENVIRONMENT.TZERO)
        self.positions = self.acc.get_position(self.code)

        print(self.acc)

        print(self.acc.market_type)
        data = QA.QA_quotation(self.code.upper(), self.start, self.end, source=QA.DATASOURCE.MONGO,
                               frequence=self.frequence, market=self.market_type, output=QA.OUTPUT_FORMAT.DATASTRUCT)

        def x1(item):
            # print(data)
            self.latest_price[item.name[1]] = item['close']
            if str(item.name[0])[0:10] != str(self.running_time)[0:10]:
                self.on_dailyclose()
                for order in self.acc.close_positions_order:
                    order.trade('closebySys', order.price,
                                order.amount, order.datetime)
                self.on_dailyopen()
                if self.market_type == QA.MARKET_TYPE.STOCK_CN:
                    print('backtest: Settle!')
                    self.acc.settle()
            self._on_1min_bar()
            self._market_data.append(item)
            self.running_time = str(item.name[0])
            self.on_bar(item)

        data.data.apply(x1, axis=1)

    def debug_currenttick(self, freq):
        data = QA.QA_fetch_get_future_transaction_realtime(
            'tdx', self.code.upper())
        self.running_mode = 'backtest'
        self.database = pymongo.MongoClient(mongo_ip).QUANTAXIS
        user = QA_User(username="******", password='******')
        port = user.new_portfolio(self.portfolio)
        self.strategy_id = self.strategy_id + 'currenttick_{}_{}'.format(str(datetime.date.today()), freq)
        self.acc = port.new_accountpro(
            account_cookie=self.strategy_id, init_cash=self.init_cash, market_type=self.market_type)
        self.positions = self.acc.get_position(self.code)
        data = data.assign(price=data.price/1000).loc[:, ['code', 'price', 'volume']].resample(
            freq).apply({'code': 'last', 'price': 'ohlc', 'volume': 'sum'}).dropna()
        data.columns = data.columns.droplevel(0)
        data = data.reset_index().set_index(['datetime', 'code'])

        def x1(item):
            self.latest_price[item.name[1]] = item['close']
            if str(item.name[0])[0:10] != str(self.running_time)[0:10]:
                self.on_dailyclose()
                self.on_dailyopen()
            self._on_1min_bar()
            self._market_data.append(item)
            self.running_time = str(item.name[0])
            self.on_bar(item)

        data.apply(x1, axis=1)

    def debug_histick(self, freq):
        data = QA.QA_fetch_get_future_transaction(
            'tdx', self.code.upper(), self.start, self.end)
        self.running_mode = 'backtest'
        self.database = pymongo.MongoClient(mongo_ip).QUANTAXIS
        user = QA_User(username="******", password='******')
        port = user.new_portfolio(self.portfolio)
        self.strategy_id = self.strategy_id + 'histick_{}_{}_{}'.format(self.start, self.end, freq)
        self.acc = port.new_accountpro(
            account_cookie=self.strategy_id, init_cash=self.init_cash, market_type=self.market_type)
        self.positions = self.acc.get_position(self.code)
        data = data.assign(price=data.price/1000).loc[:, ['code', 'price', 'volume']].resample(
            freq).apply({'code': 'last', 'price': 'ohlc', 'volume': 'sum'}).dropna()
        data.columns = data.columns.droplevel(0)
        data = data.reset_index().set_index(['datetime', 'code'])

        def x1(item):
            self.latest_price[item.name[1]] = item['close']
            if str(item.name[0])[0:10] != str(self.running_time)[0:10]:
                self.on_dailyclose()
                self.on_dailyopen()
            self._on_1min_bar()
            self._market_data.append(item)
            self.running_time = str(item.name[0])
            self.on_bar(item)

        data.apply(x1, axis=1)

    def subscribe_data(self, code, frequence, data_host, data_port, data_user, data_password, model='py'):
        """[summary]

        Arguments:
            code {[type]} -- [description]
            frequence {[type]} -- [description]
        """

        if frequence.endswith('min'):
            if model == 'py':
                self.sub = subscriber(exchange='realtime_{}_{}'.format(
                    frequence, code), host=data_host, port=data_port, user=data_user, password=data_password)
            elif model == 'rust':
                self.sub = subscriber_routing(exchange='realtime_{}'.format(
                    code), routing_key = frequence, host=data_host, port=data_port, user=data_user, password=data_password)
            self.sub.callback = self.callback
        elif frequence.endswith('s'):


            import re
            self._num_cached  = 2*int(re.findall(r'\d+',self.frequence)[0])
            self.sub = subscriber_routing(exchange='CTPX', routing_key=code, host=data_host, port=data_port, user=data_user, password=data_password)
            self.sub.callback = self.second_callback
        elif frequence.endswith('tick'):
            self._num_cached = 1
            self.sub = subscriber_routing(exchange='CTPX', routing_key=code, host=data_host, port=data_port, user=data_user, password=data_password)
            self.sub.callback = self.tick_callback


    def subscribe_multi(self, codelist, frequence, data_host, data_port, data_user, data_password, model='py'):
        if frequence.endswith('min'):
            if model == 'rust':
                self.sub = subscriber_routing(exchange='realtime_{}'.format(
                    codelist[0]), routing_key=frequence, host=data_host, port=data_port, user=data_user, password=data_password)
                for item in codelist[1:]:
                    self.sub.add_sub(exchange='realtime_{}'.format(
                        item), routing_key=frequence)
            elif model == 'py':
                self.sub = subscriber_routing(exchange='realtime_{}'.format(
                    codelist[0].lower()), routing_key=frequence, host=data_host, port=data_port, user=data_user, password=data_password)
                for item in codelist[1:]:
                    print(item)
                    self.sub.add_sub(exchange='realtime_{}'.format(
                        item.lower()), routing_key=frequence)
            self.sub.callback = self.callback
        elif frequence.endswith('tick'):

            self._num_cached = 1
            self.sub = subscriber_routing(exchange='CTPX', routing_key=codelist[0].lower(), host=data_host, port=data_port, user=data_user, password=data_password)
            for item in codelist[1:]:
                print(item)
                self.sub.add_sub(exchange='CTPX', routing_key=item.lower())

            self.sub.callback = self.tick_callback


    @property
    def old_data(self):
        return self._old_data

    def update(self):
        """
        此处是切换bar的时候的节点
        """
        self._old_data = self._market_data
        self._on_1min_bar()

    @property
    def market_datetime(self):
        return self.market_data.index.levels[0]

    @property
    def market_data(self):

        if self.running_mode == 'sim':
            return self._market_data
        elif self.running_mode == 'backtest':
            return pd.concat(self._market_data[-100:], axis=1, sort=False).T

    def force_close(self):
        # 强平
        if self.positions.volume_long > 0:
            self.send_order('SELL', 'CLOSE', price=self.positions.last_price,
                            volume=self.positions.volume_long)
        if self.positions.volume_short > 0:
            self.send_order('BUY', 'CLOSE', price=self.positions.last_price,
                            volume=self.positions.volume_short)

    def upcoming_data(self, new_bar):
        """upcoming_bar :

        Arguments:
            new_bar {pd.DataFrame} -- [description]
        """
        code = new_bar.index.levels[1][0]
        if len(self._old_data)> 0:
            self._market_data = pd.concat([self._old_data, new_bar], sort=False)
        else:
            self._market_data = new_bar
        #QA.QA_util_log_info(self._market_data)

        if self.isupdate:
            self.update()
            self.isupdate = False

        self.update_account()
        if isinstance(self.code, str):
            self.positions.on_price_change(float(self.latest_price[code]))
        else:
            for item in self.code:
                self.acc.get_position(item).on_price_change(float(self.latest_price[code]))
        self.on_bar(json.loads(new_bar.reset_index().to_json(orient='records'))[0])

    def ind2str(self, ind, ind_type):
        z = ind.tail(1).reset_index().to_dict(orient='records')[0]
        return json.dumps({'topic': ind_type, 'code': self.code, 'type': self.frequence, 'data': z})

    def second_callback(self, a, b, c, body):
        """在strategy的callback中,我们需要的是

        1. 更新数据
        2. 更新bar
        3. 更新策略状态
        4. 推送事件

        Arguments:
            a {[type]} -- [description]
            b {[type]} -- [description]
            c {[type]} -- [description]
            body {[type]} -- [description]
        
        second ==> 2*second tick
        
        b'{"ask_price_1": 4145.0, "ask_price_2": 0, "ask_price_3": 0, "ask_price_4": 0, "ask_price_5": 0, 
        "ask_volume_1": 69, "ask_volume_2": 0, "ask_volume_3": 0, "ask_volume_4": 0, "ask_volume_5": 0, 
        "average_price": 61958.14258714826, 
        "bid_price_1": 4143.0, "bid_price_2": 0, "bid_price_3": 0, "bid_price_4": 0, "bid_price_5": 0, 
        "bid_volume_1": 30, "bid_volume_2": 0, "bid_volume_3": 0, "bid_volume_4": 0, "bid_volume_5": 0, 
        "datetime": "2019-11-20 01:57:08", "exchange": "SHFE", "gateway_name": "ctp", 
        "high_price": 4152.0, "last_price": 4144.0, "last_volume": 0,
        "limit_down": 3872.0, "limit_up": 4367.0, "local_symbol": "ag1912.SHFE", 
        "low_price": 4105.0, "name": "", "open_interest": 277912.0, "open_price": 4140.0, 
        "preSettlementPrice": 4120.0, "pre_close": 4155.0, 
        "symbol": "ag1912", 
        "volume": 114288}'


        tick 会基于热数据的量 self._num_cached 来判断更新/重采样
        
        """

        self.new_data = json.loads(str(body, encoding='utf-8'))

        self._cached_data.append(self.new_data)
        self.latest_price[self.code] = self.new_data['last_price']


        # if len(self._cached_data) == self._num_cached:
        #     self.isupdate = True



        if len(self._cached_data) > 3*self._num_cached:
            # 控制缓存数据量
            self._cached_data = self._cached_data[self._num_cached:]

        data= pd.DataFrame(self._cached_data).loc[:,['datetime','last_price', 'volume']]
        data = data.assign(datetime= pd.to_datetime(data.datetime)).set_index('datetime').resample(
            self.frequence).apply({'last_price': 'ohlc', 'volume': 'last'}).dropna()
        data.columns = data.columns.droplevel(0)

        data = data.assign(volume=data.volume.diff(), code=self.code)
        data = data.reset_index().set_index(['datetime', 'code'])

        self.acc.on_price_change(self.code, self.latest_price[self.code])
        # .loc[:, ['open', 'high', 'low', 'close', 'volume', 'tradetime']]
        now = datetime.datetime.now()
        if now.hour == 20 and now.minute == 59 and now.second < 10:
            self.daily_func()
            time.sleep(10)

        self.running_time = self.new_data['datetime']
        #print(data.iloc[-1].index[0])
        if self.dt != data.index[-1][0]:
            self.isupdate = True
            self.dt = data.index[-1][0]
        self.upcoming_data(data.tail(1))

    def tick_callback(self, a, b, c, body):
        self.new_data = json.loads(str(body, encoding='utf-8'))
        self.on_tick(self.new_data)

    def get_code_marketdata(self, code):
        return self.market_data.loc[(slice(None), code), :]

    def get_current_marketdata(self):
        return self.market_data.loc[(self.running_time, slice(None)), :]


    def callback(self, a, b, c, body):
        """在strategy的callback中,我们需要的是

        1. 更新数据
        2. 更新bar
        3. 更新策略状态
        4. 推送事件

        Arguments:
            a {[type]} -- [description]
            b {[type]} -- [description]
            c {[type]} -- [description]
            body {[type]} -- [description]
        """

        self.new_data = json.loads(str(body, encoding='utf-8'))
        #print(self.new_data)
        self.latest_price[self.new_data['code']] = self.new_data['close']

        if self.dt != str(self.new_data['datetime'])[0:16]:
            # [0:16]是分钟线位数
            print('update!!!!!!!!!!!!')
            self.dt = str(self.new_data['datetime'])[0:16]
            self.isupdate = True

        self.acc.on_price_change(self.new_data['code'], self.new_data['close'])
        # .loc[:, ['open', 'high', 'low', 'close', 'volume', 'tradetime']]

        bar = pd.DataFrame([self.new_data]).set_index(['datetime', 'code'])

        now = datetime.datetime.now()
        if now.hour == 20 and now.minute == 59 and now.second < 10:
            self.daily_func()
            time.sleep(10)

        # res = self.job_control.find_one(
        #     {'strategy_id': self.strategy_id, 'strategy_id': self.strategy_id})
        # self.control_status(res)
        self.running_time = self.new_data['datetime']
        print('send to upcoming data')
        self.upcoming_data(bar)

    def control_status(self, res):
        print(res)

    def add_subscriber(self, qaproid):
        """Add a subscriber
        增加订阅者的QAPRO_ID

        """
        self.subscriber_client.insert_one(
            {'strategy_id': self.strategy_id, 'user_id': qaproid})

    @property
    def subscriber_list(self):
        """订阅者

        Returns:
            [type] -- [description]
        """

        return list(set([item['user_id'] for item in self.subscriber_client.find({'strategy_id': self.strategy_id})]))

    def load_strategy(self):
        raise NotImplementedError

    def on_dailyopen(self):
        pass

    def on_dailyclose(self):
        pass

    def on_bar(self, bar):
        raise NotImplementedError

    def on_tick(self, tick):
        raise NotImplementedError

    def _on_1min_bar(self):
        #raise NotImplementedError
        if len(self._systemvar.keys()) > 0:
            self._signal.append(copy.deepcopy(self._systemvar))
        try:
          self.on_1min_bar()
        except:
          pass

    def on_1min_bar(self):
        raise NotImplementedError

    def on_5min_bar(self):
        raise NotImplementedError

    def on_15min_bar(self):
        raise NotImplementedError

    def on_30min_bar(self):
        raise NotImplementedError

    def order_handler(self):
        self._orders = {}

    def daily_func(self):
        QA.QA_util_log_info('DAILY FUNC')

    def risk_check(self):
        pass

    def plot(self, name, data, format):
        """ plot是可以存储你的临时信息的接口, 后期会接入可视化



        Arguments:
            name {[type]} -- [description]
            data {[type]} -- [description]
            format {[type]} -- [description]
        """
        self._systemvar[name] = {'datetime': copy.deepcopy(str(
            self.running_time)), 'value': data, 'format': format}

    def get_code(self):
        if isinstance(self.code, str):
            return self.code
        else:
            return self.code[0]
    def check_order(self, direction, offset, code= None):
        """[summary]
        同方向不开仓  只对期货市场做限制

        buy - open
        sell - close
        """
        if code == None:
            code = self.get_code()


        if self.market_type == QA.MARKET_TYPE.FUTURE_CN:

                if self.last_order_towards[code][direction] == str(offset):
                    return False
                else:
                    return True
        else:
            return True

    def on_ordererror(self, direction, offset, price, volume):
        print('order Error ')

    def receive_simpledeal(self,
                           code: str,
                           trade_time,
                           trade_amount,
                           direction,
                           offset,
                           trade_price,
                           message='sell_open'):
        self.send_order(direction=direction, offset=offset,
                        volume=trade_amount, price=trade_price, order_id=QA.QA_util_random_with_topic(self.strategy_id))

    def send_order(self,  direction='BUY', offset='OPEN', price=3925, volume=10, order_id='', code = None):
        if code == None:
            code = self.get_code()

        towards = eval('ORDER_DIRECTION.{}_{}'.format(direction, offset))
        order_id = str(uuid.uuid4()) if order_id == '' else order_id

        if isinstance(price, float):
            pass
        elif isinstance(price, pd.Series):
            price = price.values[0]

        if self.running_mode == 'sim':
            # 在此处拦截无法下单的订单
            if (direction == 'BUY' and self.latest_price[code] <= price) or (direction == 'SELL' and self.latest_price[code] >= price):
                QA.QA_util_log_info(
                    '============ {} SEND ORDER =================='.format(order_id))
                QA.QA_util_log_info('direction{} offset {} price{} volume{}'.format(
                    direction, offset, price, volume))

                if self.check_order(direction, offset, code=code):
                    #self.last_order_towards = {'BUY': '', 'SELL': ''}
                    self.last_order_towards[code][direction] = offset
                    now = str(datetime.datetime.now())

                    order = self.acc.send_order(
                        code=code, towards=towards, price=price, amount=volume, order_id=order_id)
                    print(order)
                    order['topic'] = 'send_order'
                    self.pub.pub(
                        json.dumps(order), routing_key=self.strategy_id)

                    self.acc.make_deal(order)
                    self.bar_order['{}_{}'.format(
                        direction, offset)] = self.bar_id
                    if self.send_wx:
                        for user in self.subscriber_list:
                            QA.QA_util_log_info(self.subscriber_list)
                            try:
                                requests.post('http://www.yutiansut.com/signal?user_id={}&template={}&strategy_id={}&realaccount={}&code={}&order_direction={}&order_offset={}&price={}&volume={}&order_time={}'.format(
                                    user, "xiadan_report", self.strategy_id, self.acc.user_id, code.lower(), direction, offset, price, volume, now))
                            except Exception as e:
                                QA.QA_util_log_info(e)

                else:
                    QA.QA_util_log_info('failed in ORDER_CHECK')
            else:
                self.on_ordererror(direction, offset, price, volume)
        elif self.running_mode == 'backtest':

            self.bar_order['{}_{}'.format(direction, offset)] = self.bar_id

            if self.market_type == 'stock_cn':
                order = self.acc.send_order(
                    code=self.code, amount=volume, time=self.running_time, towards=towards, price=price)
                order.trade(order.order_id, order.price,
                            order.amount, order.datetime)
            else:
                self.acc.receive_simpledeal(
                    code=self.code, trade_time=self.running_time, trade_towards=towards, trade_amount=volume, trade_price=price, order_id=order_id, realorder_id=order_id, trade_id=order_id)
            self.positions = self.acc.get_position(self.code)

    def update_account(self):
        if self.running_mode == 'sim':
            QA.QA_util_log_info('{} UPDATE ACCOUNT'.format(
                str(datetime.datetime.now())))

            self.accounts = self.acc.account_msg
            self.orders = self.acc.orders
            if isinstance(self.code, str):
                self.positions = self.acc.get_position(self.code)
            else:
                pass
            self.trades = self.acc.trades
            self.updatetime = self.acc.dtstr
        elif self.running_mode == 'backtest':
            self.positions = self.acc.get_position(self.code)

    def get_exchange(self, code):
        return self.market_preset.get_exchange(code)

    def get_positions(self, code):
        if self.running_mode == 'sim':
            self.update_account()
            return self.acc.get_position(code)
        elif self.running_mode == 'backtest':
            return self.acc.get_position(code)

    def get_cash(self):
        if self.running_mode == 'sim':
            self.update_account()
            return self.accounts.get('available', '')
        elif self.running_mode == 'backtest':
            return self.acc.cash_available

    def run(self):

        while True:
            time.sleep(self.risk_check_gap)
            self.risk_check()
Exemplo n.º 2
0
class QAStrategyStockBase(QAStrategyCTABase):
    def __init__(self,
                 code=['000001'],
                 frequence='1min',
                 strategy_id='QA_STRATEGY',
                 risk_check_gap=1,
                 portfolio='default',
                 start='2019-01-01',
                 end='2019-10-21',
                 send_wx=False,
                 market_type='stock_cn',
                 data_host=eventmq_ip,
                 data_port=eventmq_port,
                 data_user=eventmq_username,
                 data_password=eventmq_password,
                 trade_host=eventmq_ip,
                 trade_port=eventmq_port,
                 trade_user=eventmq_username,
                 trade_password=eventmq_password,
                 taskid=None,
                 mongo_ip=mongo_ip):
        super().__init__(code=code,
                         frequence=frequence,
                         strategy_id=strategy_id,
                         risk_check_gap=risk_check_gap,
                         portfolio=portfolio,
                         start=start,
                         end=end,
                         send_wx=send_wx,
                         data_host=eventmq_ip,
                         data_port=eventmq_port,
                         data_user=eventmq_username,
                         data_password=eventmq_password,
                         trade_host=eventmq_ip,
                         trade_port=eventmq_port,
                         trade_user=eventmq_username,
                         trade_password=eventmq_password,
                         taskid=taskid,
                         mongo_ip=mongo_ip)

        self.code = code
        self.send_wx = send_wx

    def subscribe_data(self, code, frequence, data_host, data_port, data_user,
                       data_password):
        """[summary]

        Arguments:
            code {[type]} -- [description]
            frequence {[type]} -- [description]
        """

        self.sub = subscriber_topic(
            exchange='realtime_stock_{}'.format(frequence),
            host=data_host,
            port=data_port,
            user=data_user,
            password=data_password,
            routing_key='')
        for item in code:
            self.sub.add_sub(exchange='realtime_stock_{}'.format(frequence),
                             routing_key=item)
        self.sub.callback = self.callback

    def upcoming_data(self, new_bar):
        """upcoming_bar :

        Arguments:
            new_bar {json} -- [description]
        """
        self._market_data = pd.concat([self._old_data, new_bar])
        # QA.QA_util_log_info(self._market_data)

        if self.isupdate:
            self.update()
            self.isupdate = False

        self.update_account()
        # self.positions.on_price_change(float(new_bar['close']))
        self.on_bar(new_bar)

    def ind2str(self, ind, ind_type):
        z = ind.tail(1).reset_index().to_dict(orient='records')[0]
        return json.dumps({
            'topic': ind_type,
            'code': self.code,
            'type': self.frequence,
            'data': z
        })

    def callback(self, a, b, c, body):
        """在strategy的callback中,我们需要的是

        1. 更新数据
        2. 更新bar
        3. 更新策略状态
        4. 推送事件

        Arguments:
            a {[type]} -- [description]
            b {[type]} -- [description]
            c {[type]} -- [description]
            body {[type]} -- [description]
        """

        self.new_data = json.loads(str(body, encoding='utf-8'))

        self.latest_price[self.new_data['code']] = self.new_data['close']

        self.running_time = self.new_data['datetime']
        if self.dt != str(self.new_data['datetime'])[0:16]:
            # [0:16]是分钟线位数
            print('update!!!!!!!!!!!!')
            self.dt = str(self.new_data['datetime'])[0:16]
            self.isupdate = True

        self.acc.on_price_change(self.new_data['code'], self.new_data['close'])
        bar = pd.DataFrame([self.new_data]).set_index(
            ['datetime',
             'code']).loc[:, ['open', 'high', 'low', 'close', 'volume']]
        self.upcoming_data(bar)

    def _debug_sim(self):
        self.running_mode = 'sim'

        self._old_data = QA.QA_fetch_stock_min(
            self.code,
            QA.QA_util_get_last_day(
                QA.QA_util_get_real_date(str(datetime.date.today()))),
            str(datetime.datetime.now()),
            format='pd',
            frequence=self.frequence).set_index(['datetime', 'code'])

        self._old_data = self._old_data.loc[:, [
            'open', 'high', 'low', 'close', 'volume'
        ]]

        self.database = pymongo.MongoClient(mongo_ip).QAREALTIME

        self.client = self.database.account
        self.subscriber_client = self.database.subscribe

        self.acc = QIFI_Account(username=self.strategy_id,
                                password=self.strategy_id,
                                trade_host=mongo_ip)
        self.acc.initial()

        self.pub = publisher_routing(exchange='QAORDER_ROUTER',
                                     host=self.trade_host,
                                     port=self.trade_port,
                                     user=self.trade_user,
                                     password=self.trade_password)

        self.subscribe_data(self.code, self.frequence, self.data_host,
                            self.data_port, self.data_user, self.data_password)

        self.database.strategy_schedule.job_control.update(
            {'strategy_id': self.strategy_id}, {
                'strategy_id': self.strategy_id,
                'taskid': self.taskid,
                'filepath': os.path.abspath(__file__),
                'status': 200
            },
            upsert=True)

        # threading.Thread(target=, daemon=True).start()
        self.sub.start()

    def run(self):
        while True:
            pass

    def debug(self):
        self.running_mode = 'backtest'
        self.database = pymongo.MongoClient(mongo_ip).QUANTAXIS
        user = QA_User(username="******", password='******')
        port = user.new_portfolio(self.portfolio)
        self.acc = port.new_accountpro(account_cookie=self.strategy_id,
                                       init_cash=self.init_cash,
                                       market_type=self.market_type,
                                       frequence=self.frequence)
        #self.positions = self.acc.get_position(self.code)

        print(self.acc)

        print(self.acc.market_type)
        data = QA.QA_quotation(self.code,
                               self.start,
                               self.end,
                               source=QA.DATASOURCE.MONGO,
                               frequence=self.frequence,
                               market=self.market_type,
                               output=QA.OUTPUT_FORMAT.DATASTRUCT)

        data.data.apply(self.x1, axis=1)

    def update_account(self):
        if self.running_mode == 'sim':
            QA.QA_util_log_info('{} UPDATE ACCOUNT'.format(
                str(datetime.datetime.now())))

            self.accounts = self.acc.account_msg
            self.orders = self.acc.orders
            self.positions = self.acc.positions

            self.trades = self.acc.trades
            self.updatetime = self.acc.dtstr
        elif self.running_mode == 'backtest':
            #self.positions = self.acc.get_position(self.code)
            self.positions = self.acc.positions

    def send_order(
        self,
        direction='BUY',
        offset='OPEN',
        code=None,
        price=3925,
        volume=10,
        order_id='',
    ):

        towards = eval('ORDER_DIRECTION.{}_{}'.format(direction, offset))
        order_id = str(uuid.uuid4()) if order_id == '' else order_id

        if self.market_type == QA.MARKET_TYPE.STOCK_CN:
            """
            在此对于股票的部分做一些转换
            """
            if towards == ORDER_DIRECTION.SELL_CLOSE:
                towards = ORDER_DIRECTION.SELL
            elif towards == ORDER_DIRECTION.BUY_OPEN:
                towards = ORDER_DIRECTION.BUY

        if isinstance(price, float):
            pass
        elif isinstance(price, pd.Series):
            price = price.values[0]

        if self.running_mode == 'sim':

            QA.QA_util_log_info(
                '============ {} SEND ORDER =================='.format(
                    order_id))
            QA.QA_util_log_info(
                'direction{} offset {} price{} volume{}'.format(
                    direction, offset, price, volume))

            if self.check_order(direction, offset):
                self.last_order_towards = {'BUY': '', 'SELL': ''}
                self.last_order_towards[direction] = offset
                now = str(datetime.datetime.now())

                order = self.acc.send_order(code=code,
                                            towards=towards,
                                            price=price,
                                            amount=volume,
                                            order_id=order_id)
                order['topic'] = 'send_order'
                self.pub.pub(json.dumps(order), routing_key=self.strategy_id)

                self.acc.make_deal(order)
                self.bar_order['{}_{}'.format(direction, offset)] = self.bar_id
                if self.send_wx:
                    for user in self.subscriber_list:
                        QA.QA_util_log_info(self.subscriber_list)
                        try:
                            "oL-C4w2WlfyZ1vHSAHLXb2gvqiMI"
                            """http://www.yutiansut.com/signal?user_id=oL-C4w1HjuPRqTIRcZUyYR0QcLzo&template=xiadan_report&\
                                        strategy_id=test1&realaccount=133496&code=rb1910&order_direction=BUY&\
                                        order_offset=OPEN&price=3600&volume=1&order_time=20190909
                            """

                            requests.post(
                                'http://www.yutiansut.com/signal?user_id={}&template={}&strategy_id={}&realaccount={}&code={}&order_direction={}&order_offset={}&price={}&volume={}&order_time={}'
                                .format(user, "xiadan_report",
                                        self.strategy_id, self.acc.user_id,
                                        code, direction, offset, price, volume,
                                        now))
                        except Exception as e:
                            QA.QA_util_log_info(e)

            else:
                QA.QA_util_log_info('failed in ORDER_CHECK')

        elif self.running_mode == 'backtest':

            self.bar_order['{}_{}'.format(direction, offset)] = self.bar_id

            self.acc.receive_simpledeal(code=code,
                                        trade_time=self.running_time,
                                        trade_towards=towards,
                                        trade_amount=volume,
                                        trade_price=price,
                                        order_id=order_id)
Exemplo n.º 3
0
class QAStrategyCTABase():
    def __init__(self,
                 code='rb1905',
                 frequence='1min',
                 strategy_id='QA_STRATEGY',
                 risk_check_gap=1,
                 portfolio='default',
                 start='2019-01-01',
                 end='2019-10-21',
                 init_cash=1000000,
                 send_wx=False,
                 data_host=eventmq_ip,
                 data_port=eventmq_port,
                 data_user=eventmq_username,
                 data_password=eventmq_password,
                 trade_host=eventmq_ip,
                 trade_port=eventmq_port,
                 trade_user=eventmq_username,
                 trade_password=eventmq_password,
                 taskid=None,
                 mongo_ip=mongo_ip):

        self.trade_host = trade_host

        self.code = code
        self.frequence = frequence
        self.strategy_id = strategy_id

        self.portfolio = portfolio

        self.data_host = data_host
        self.data_port = data_port
        self.data_user = data_user
        self.data_password = data_password
        self.trade_host = trade_host
        self.trade_port = trade_port
        self.trade_user = trade_user
        self.trade_password = trade_password

        self.start = start
        self.end = end
        self.init_cash = init_cash
        self.taskid = taskid

        self.running_time = ''

        self.market_preset = QA.QAARP.MARKET_PRESET()
        self._market_data = []
        self.risk_check_gap = risk_check_gap

        self.isupdate = False
        self.new_data = {}
        self._systemvar = {}
        self._signal = []
        self.send_wx = send_wx
        self.last_order_towards = {'BUY': '', 'SELL': ''}
        self.dt = ''
        if isinstance(self.code, str):
            self.market_type = MARKET_TYPE.FUTURE_CN if re.search(
                r'[a-zA-z]+', self.code) else MARKET_TYPE.STOCK_CN
        else:
            self.market_type = MARKET_TYPE.FUTURE_CN if re.search(
                r'[a-zA-z]+', self.code[0]) else MARKET_TYPE.STOCK_CN

        self.bar_order = {
            'BUY_OPEN': 0,
            'SELL_OPEN': 0,
            'BUY_CLOSE': 0,
            'SELL_CLOSE': 0
        }

    @property
    def bar_id(self):
        return len(self._market_data)

    def _debug_sim(self):

        self.running_mode = 'sim'
        if self.frequence.endswith('min'):
            self._old_data = QA.QA_fetch_get_future_min(
                'tdx', self.code.upper(),
                QA.QA_util_get_last_day(
                    QA.QA_util_get_real_date(str(datetime.date.today()))),
                str(datetime.datetime.now()),
                self.frequence)[:-1].set_index(['datetime', 'code'])
            self._old_data = self._old_data.assign(
                volume=self._old_data.trade
            ).loc[:, ['open', 'high', 'low', 'close', 'volume']]
        else:
            pass

        self.database = pymongo.MongoClient(mongo_ip).QAREALTIME

        self.client = self.database.account
        self.subscriber_client = self.database.subscribe

        self.acc = QIFI_Account(username=self.strategy_id,
                                password=self.strategy_id,
                                trade_host=mongo_ip,
                                init_cash=self.init_cash)
        self.acc.initial()

        self.pub = publisher_routing(exchange='QAORDER_ROUTER',
                                     host=self.trade_host,
                                     port=self.trade_port,
                                     user=self.trade_user,
                                     password=self.trade_password)

        self.subscribe_data(self.code.lower(), self.frequence, self.data_host,
                            self.data_port, self.data_user, self.data_password)

        self.database.strategy_schedule.job_control.update(
            {'strategy_id': self.strategy_id}, {
                'strategy_id': self.strategy_id,
                'taskid': self.taskid,
                'filepath': os.path.abspath(__file__),
                'status': 200
            },
            upsert=True)

    def debug_sim(self):
        self._debug_sim()
        threading.Thread(target=self.sub.start, daemon=True).start()

    def run_sim(self):
        self._debug_sim()

        self.sub.start()

    def run_backtest(self):
        self.debug()
        self.acc.save()

        risk = QA_Risk(self.acc)
        risk.save()

        try:
            """add rank flow if exist

            QARank是我们内部用于评价策略ELO的库 此处并不影响正常使用
            """
            from QARank import QA_Rank
            QA_Rank(self.acc).send()
        except:
            pass

    def debug(self):
        self.running_mode = 'backtest'
        self.database = pymongo.MongoClient(mongo_ip).QUANTAXIS
        user = QA_User(username="******", password='******')
        port = user.new_portfolio(self.portfolio)
        self.acc = port.new_accountpro(account_cookie=self.strategy_id,
                                       init_cash=self.init_cash,
                                       market_type=self.market_type)
        self.positions = self.acc.get_position(self.code)

        print(self.acc)

        print(self.acc.market_type)
        data = QA.QA_quotation(self.code.upper(),
                               self.start,
                               self.end,
                               source=QA.DATASOURCE.MONGO,
                               frequence=self.frequence,
                               market=self.market_type,
                               output=QA.OUTPUT_FORMAT.DATASTRUCT)

        def x1(item):
            # print(data)

            if str(item.name[0])[0:10] != str(self.running_time)[0:10]:
                self.on_dailyclose()
                self.on_dailyopen()
                if self.market_type == QA.MARKET_TYPE.STOCK_CN:
                    print('backtest: Settle!')
                    self.acc.settle()
            self._on_1min_bar()
            self._market_data.append(item)
            self.running_time = str(item.name[0])
            self.on_bar(item)

        data.data.apply(x1, axis=1)

    def subscribe_data(self, code, frequence, data_host, data_port, data_user,
                       data_password):
        """[summary]

        Arguments:
            code {[type]} -- [description]
            frequence {[type]} -- [description]
        """

        self.sub = subscriber(exchange='realtime_{}_{}'.format(
            frequence, code),
                              host=data_host,
                              port=data_port,
                              user=data_user,
                              password=data_password)
        self.sub.callback = self.callback

    def subscribe_multi(self, codelist, frequence, data_host, data_port,
                        data_user, data_password):

        self.sub = subscriber_topic(exchange='realtime_{}'.format(frequence),
                                    host=data_host,
                                    port=data_port,
                                    user=data_user,
                                    password=data_password)
        for item in codelist:
            self.sub.add_sub(exchange='realtime_{}'.format(frequence),
                             routing_key=item)
        self.sub.callback = self.callback

    @property
    def old_data(self):
        return self._old_data

    def update(self):
        """
        此处是切换bar的时候的节点
        """
        self._old_data = self._market_data
        self._on_1min_bar()

    @property
    def market_datetime(self):
        return self.market_data.index.levels[0]

    @property
    def market_data(self):

        if self.running_mode == 'sim':
            return self._market_data
        elif self.running_mode == 'backtest':
            return pd.concat(self._market_data[-100:], axis=1, sort=False).T

    def force_close(self):
        # 强平
        if self.positions.volume_long > 0:
            self.send_order('SELL',
                            'CLOSE',
                            price=self.positions.last_price,
                            volume=self.positions.volume_long)
        if self.positions.volume_short > 0:
            self.send_order('BUY',
                            'CLOSE',
                            price=self.positions.last_price,
                            volume=self.positions.volume_short)

    def upcoming_data(self, new_bar):
        """upcoming_bar :

        Arguments:
            new_bar {json} -- [description]
        """
        self._market_data = pd.concat([self._old_data, new_bar])
        # QA.QA_util_log_info(self._market_data)

        if self.isupdate:
            self.update()
            self.isupdate = False

        self.update_account()
        self.positions.on_price_change(float(self.new_data['close']))
        self.on_bar(self.new_data)

    def ind2str(self, ind, ind_type):
        z = ind.tail(1).reset_index().to_dict(orient='records')[0]
        return json.dumps({
            'topic': ind_type,
            'code': self.code,
            'type': self.frequence,
            'data': z
        })

    def callback(self, a, b, c, body):
        """在strategy的callback中,我们需要的是

        1. 更新数据
        2. 更新bar
        3. 更新策略状态
        4. 推送事件

        Arguments:
            a {[type]} -- [description]
            b {[type]} -- [description]
            c {[type]} -- [description]
            body {[type]} -- [description]
        """

        self.new_data = json.loads(str(body, encoding='utf-8'))

        if self.dt != str(self.new_data['datetime'])[0:16]:
            print('update!!!!!!!!!!!!')
            self.dt = str(self.new_data['datetime'])[0:16]
            self.isupdate = True

        self.acc.on_price_change(self.code, self.new_data['close'])
        # .loc[:, ['open', 'high', 'low', 'close', 'volume', 'tradetime']]
        bar = pd.DataFrame([self.new_data]).set_index(['datetime', 'code'])
        now = datetime.datetime.now()
        if now.hour == 20 and now.minute == 59 and now.second < 10:
            self.daily_func()
            time.sleep(10)

        # res = self.job_control.find_one(
        #     {'strategy_id': self.strategy_id, 'strategy_id': self.strategy_id})
        # self.control_status(res)
        self.running_time = self.new_data['datetime']
        self.upcoming_data(bar)

    def control_status(self, res):
        print(res)

    def add_subscriber(self, qaproid):
        """Add a subscriber
        增加订阅者的QAPRO_ID

        """
        self.subscriber_client.insert_one({
            'strategy_id': self.strategy_id,
            'user_id': qaproid
        })

    @property
    def subscriber_list(self):
        """订阅者

        Returns:
            [type] -- [description]
        """

        return list(
            set([
                item['user_id'] for item in self.subscriber_client.find(
                    {'strategy_id': self.strategy_id})
            ]))

    def load_strategy(self):
        raise NotImplementedError

    def on_dailyopen(self):
        pass

    def on_dailyclose(self):
        pass

    def on_bar(self, bar):
        raise NotImplementedError

    def _on_1min_bar(self):
        #raise NotImplementedError
        if len(self._systemvar.keys()) > 0:
            self._signal.append(copy.deepcopy(self._systemvar))

    def on_1min_bar(self):
        raise NotImplementedError

    def on_5min_bar(self):
        raise NotImplementedError

    def on_15min_bar(self):
        raise NotImplementedError

    def on_30min_bar(self):
        raise NotImplementedError

    def order_handler(self):
        self._orders = {}

    def daily_func(self):
        QA.QA_util_log_info('DAILY FUNC')

    def risk_check(self):
        pass

    def plot(self, name, data, format):
        """ plot是可以存储你的临时信息的接口, 后期会接入可视化



        Arguments:
            name {[type]} -- [description]
            data {[type]} -- [description]
            format {[type]} -- [description]
        """
        self._systemvar[name] = {
            'datetime': copy.deepcopy(str(self.running_time)),
            'value': data,
            'format': format
        }

    def check_order(self, direction, offset):
        """[summary]
        同方向不开仓  只对期货市场做限制

        buy - open
        sell - close
        """
        if self.market_type == QA.MARKET_TYPE.FUTURE_CN:
            if self.last_order_towards[direction] == str(offset):
                return False
            else:
                return True
        else:
            return True

    def receive_simpledeal(self,
                           code: str,
                           trade_time,
                           trade_amount,
                           direction,
                           offset,
                           trade_price,
                           message='sell_open'):
        self.send_order(direction=direction,
                        offset=offset,
                        volume=trade_amount,
                        price=trade_price,
                        order_id=QA.QA_util_random_with_topic(
                            self.strategy_id))

    def send_order(
        self,
        direction='BUY',
        offset='OPEN',
        price=3925,
        volume=10,
        order_id='',
    ):

        towards = eval('ORDER_DIRECTION.{}_{}'.format(direction, offset))
        order_id = str(uuid.uuid4()) if order_id == '' else order_id

        if isinstance(price, float):
            pass
        elif isinstance(price, pd.Series):
            price = price.values[0]

        if self.running_mode == 'sim':

            QA.QA_util_log_info(
                '============ {} SEND ORDER =================='.format(
                    order_id))
            QA.QA_util_log_info(
                'direction{} offset {} price{} volume{}'.format(
                    direction, offset, price, volume))

            if self.check_order(direction, offset):
                self.last_order_towards = {'BUY': '', 'SELL': ''}
                self.last_order_towards[direction] = offset
                now = str(datetime.datetime.now())

                order = self.acc.send_order(code=self.code,
                                            towards=towards,
                                            price=price,
                                            amount=volume,
                                            order_id=order_id)
                order['topic'] = 'send_order'
                self.pub.pub(json.dumps(order), routing_key=self.strategy_id)

                self.acc.make_deal(order)
                self.bar_order['{}_{}'.format(direction, offset)] = self.bar_id
                if self.send_wx:
                    for user in self.subscriber_list:
                        QA.QA_util_log_info(self.subscriber_list)
                        try:
                            "oL-C4w2WlfyZ1vHSAHLXb2gvqiMI"
                            """http://www.yutiansut.com/signal?user_id=oL-C4w1HjuPRqTIRcZUyYR0QcLzo&template=xiadan_report&\
                                        strategy_id=test1&realaccount=133496&code=rb1910&order_direction=BUY&\
                                        order_offset=OPEN&price=3600&volume=1&order_time=20190909
                            """

                            requests.post(
                                'http://www.yutiansut.com/signal?user_id={}&template={}&strategy_id={}&realaccount={}&code={}&order_direction={}&order_offset={}&price={}&volume={}&order_time={}'
                                .format(user, "xiadan_report",
                                        self.strategy_id, self.acc.user_id,
                                        self.code.lower(), direction, offset,
                                        price, volume, now))
                        except Exception as e:
                            QA.QA_util_log_info(e)

            else:
                QA.QA_util_log_info('failed in ORDER_CHECK')

        elif self.running_mode == 'backtest':

            self.bar_order['{}_{}'.format(direction, offset)] = self.bar_id

            self.acc.receive_simpledeal(code=self.code,
                                        trade_time=self.running_time,
                                        trade_towards=towards,
                                        trade_amount=volume,
                                        trade_price=price,
                                        order_id=order_id)
            self.positions = self.acc.get_position(self.code)

    def update_account(self):
        if self.running_mode == 'sim':
            QA.QA_util_log_info('{} UPDATE ACCOUNT'.format(
                str(datetime.datetime.now())))

            self.accounts = self.acc.account_msg
            self.orders = self.acc.orders
            self.positions = self.acc.get_position(self.code)
            self.trades = self.acc.trades
            self.updatetime = self.acc.dtstr
        elif self.running_mode == 'backtest':
            self.positions = self.acc.get_position(self.code)

    def get_exchange(self, code):
        return self.market_preset.get_exchange(code)

    def get_positions(self, code):
        if self.running_mode == 'sim':
            self.update_account()
            return self.positions
        elif self.running_mode == 'backtest':
            return self.acc.get_position(code)

    def get_cash(self):
        if self.running_mode == 'sim':
            self.update_account()
            return self.accounts.get('available', '')
        elif self.running_mode == 'backtest':
            return self.acc.cash_available

    def run(self):

        while True:
            time.sleep(self.risk_check_gap)
            self.risk_check()
Exemplo n.º 4
0
    columnsList.append('rate')
    countRange=jyrq #list(range(1,len(jyrq)))
    columnsList.extend(countRange)
    return pd.DataFrame(columns=columnsList)



dfp = createFrame([ "d{}".format(i) for i in range(0,nday+1)])
dfold=pd.DataFrame(columns = [""])
#print(dfp)

#change_day=get_trade_day_bar(unit='M',n=-1,start_date='2015-01-01',end_date='2021-04-27').date.astype('str').tolist()
#data=QA.QA_fetch_index_day_adv(code=codes,start=start,end=end)
#acc=QIFI_Account('FOF','FOF',model='BACKTEST',trade_host='172.19.0.2',nodatabase=False)
acc =  QIFI_Account(username='******', password='******', model= "BACKTEST",init_cash=5000000)
acc.initial()
#acc.reload()
print(trade_day)
print(acc.positions)
print(acc.trades)

for day in trade_day:
    #print(stock_list)
    start = jy_date_list(day,-1)[-2]
    dfp,dfold=ss.get_stock(start,nday)

    dfp = ss.op_stock(dfp,dfold)
    #print("selected:",dfp)
    #z最多购买个数
    num=5
    #持有5d
Exemplo n.º 5
0
class QAStrategyStockBase(QAStrategyCTABase):
    def __init__(self,
                 code='rb1905',
                 frequence='1min',
                 strategy_id='QA_STRATEGY',
                 risk_check_gap=1,
                 portfolio='default',
                 start='2019-01-01',
                 end='2019-10-21',
                 data_host=eventmq_ip,
                 data_port=eventmq_port,
                 data_user=eventmq_username,
                 data_password=eventmq_password,
                 trade_host=eventmq_ip,
                 trade_port=eventmq_port,
                 trade_user=eventmq_username,
                 trade_password=eventmq_password,
                 taskid=None,
                 mongo_ip=mongo_ip):
        super().__init__(code=code,
                         frequence=frequence,
                         strategy_id=strategy_id,
                         risk_check_gap=risk_check_gap,
                         portfolio=portfolio,
                         start=start,
                         end=end,
                         data_host=eventmq_ip,
                         data_port=eventmq_port,
                         data_user=eventmq_username,
                         data_password=eventmq_password,
                         trade_host=eventmq_ip,
                         trade_port=eventmq_port,
                         trade_user=eventmq_username,
                         trade_password=eventmq_password,
                         taskid=taskid,
                         mongo_ip=mongo_ip)

        self.code = code

    def subscribe_data(self, code, frequence, data_host, data_port, data_user,
                       data_password):
        """[summary]

        Arguments:
            code {[type]} -- [description]
            frequence {[type]} -- [description]
        """
        self.sub = subscriber_topic(
            exchange='realtime_stock_{}'.format(frequence),
            host=data_host,
            port=data_port,
            user=data_user,
            password=data_password,
            routing_key='')
        for item in code:
            self.sub.add_sub(exchange='realtime_stock_{}'.format(frequence),
                             routing_key=item)
        self.sub.callback = self.callback

    def upcoming_data(self, new_bar):
        """upcoming_bar :

        Arguments:
            new_bar {json} -- [description]
        """
        self._market_data = pd.concat([self._old_data, new_bar])
        # QA.QA_util_log_info(self._market_data)

        if self.isupdate:
            self.update()
            self.isupdate = False

        self.update_account()
        # self.positions.on_price_change(float(new_bar['close']))
        self.on_bar(new_bar)

    def ind2str(self, ind, ind_type):
        z = ind.tail(1).reset_index().to_dict(orient='records')[0]
        return json.dumps({
            'topic': ind_type,
            'code': self.code,
            'type': self.frequence,
            'data': z
        })

    def callback(self, a, b, c, body):
        """在strategy的callback中,我们需要的是

        1. 更新数据
        2. 更新bar
        3. 更新策略状态
        4. 推送事件

        Arguments:
            a {[type]} -- [description]
            b {[type]} -- [description]
            c {[type]} -- [description]
            body {[type]} -- [description]
        """

        self.new_data = json.loads(str(body, encoding='utf-8'))
        self.running_time = self.new_data['datetime']
        if float(self.new_data['datetime'][-9:]) == 0:
            self.isupdate = True
        self.acc.on_price_change(self.new_data['code'], self.new_data['close'])
        bar = pd.DataFrame([self.new_data]).set_index(
            ['datetime',
             'code']).loc[:, ['open', 'high', 'low', 'close', 'volume']]
        self.upcoming_data(bar)

    def run_sim(self):
        self.running_mode = 'sim'

        self._old_data = QA.QA_fetch_stock_min(
            self.code,
            QA.QA_util_get_last_day(
                QA.QA_util_get_real_date(str(datetime.date.today()))),
            str(datetime.datetime.now()),
            format='pd',
            frequence=self.frequence).set_index(['datetime', 'code'])

        self._old_data = self._old_data.loc[:, [
            'open', 'high', 'low', 'close', 'volume'
        ]]

        self.database = pymongo.MongoClient(mongo_ip).QAREALTIME

        self.client = self.database.account
        self.subscriber_client = self.database.subscribe

        self.acc = QIFI_Account(username=self.strategy_id,
                                password=self.strategy_id,
                                trade_host=mongo_ip)
        self.acc.initial()

        self.pub = publisher_routing(exchange='QAORDER_ROUTER',
                                     host=self.trade_host,
                                     port=self.trade_port,
                                     user=self.trade_user,
                                     password=self.trade_password)

        self.subscribe_data(self.code, self.frequence, self.data_host,
                            self.data_port, self.data_user, self.data_password)

        self.add_subscriber('oL-C4w1HjuPRqTIRcZUyYR0QcLzo')
        self.database.strategy_schedule.job_control.update(
            {'strategy_id': self.strategy_id}, {
                'strategy_id': self.strategy_id,
                'taskid': self.taskid,
                'filepath': os.path.abspath(__file__),
                'status': 200
            },
            upsert=True)

        # threading.Thread(target=, daemon=True).start()
        self.sub.start()

    def run(self):
        while True:
            pass

    def update_account(self):
        if self.running_mode == 'sim':
            QA.QA_util_log_info('{} UPDATE ACCOUNT'.format(
                str(datetime.datetime.now())))

            self.accounts = self.acc.account_msg
            self.orders = self.acc.orders
            self.positions = self.acc.positions

            self.trades = self.acc.trades
            self.updatetime = self.acc.dtstr
        elif self.running_mode == 'backtest':
            #self.positions = self.acc.get_position(self.code)
            self.positions = self.acc.positions
Exemplo n.º 6
0
class QAStrategyStockBase(QAStrategyCTABase):
    def __init__(self,
                 code=['000001'],
                 frequence='1min',
                 strategy_id='QA_STRATEGY',
                 risk_check_gap=1,
                 portfolio='default',
                 start='2019-01-01',
                 end='2019-10-21',
                 send_wx=False,
                 market_type='stock_cn',
                 data_host=eventmq_ip,
                 data_port=eventmq_port,
                 data_user=eventmq_username,
                 data_password=eventmq_password,
                 trade_host=eventmq_ip,
                 trade_port=eventmq_port,
                 trade_user=eventmq_username,
                 trade_password=eventmq_password,
                 taskid=None,
                 mongo_ip=mongo_ip):
        super().__init__(code=code,
                         frequence=frequence,
                         strategy_id=strategy_id,
                         risk_check_gap=risk_check_gap,
                         portfolio=portfolio,
                         start=start,
                         end=end,
                         send_wx=send_wx,
                         data_host=eventmq_ip,
                         data_port=eventmq_port,
                         data_user=eventmq_username,
                         data_password=eventmq_password,
                         trade_host=eventmq_ip,
                         trade_port=eventmq_port,
                         trade_user=eventmq_username,
                         trade_password=eventmq_password,
                         taskid=taskid,
                         mongo_ip=mongo_ip)

        self.code = code
        self.send_wx = send_wx
        self.dtcode = {}
        stock_pool_pd = pd.read_csv(
            "/root/qa_strategy/stock_strategy/stock_pool.csv",
            encoding='utf-8',
            converters={'code': str})
        self.stock_pool_list = stock_pool_pd['code'].tolist()
        '''

        '''
        print('订阅远程行情开始:')
        self.subscriber = subscriber_topic(host='www.yutiansut.com',
                                           port='5678',
                                           exchange='QARealtimePro_FIX',
                                           durable=False,
                                           vhost='/',
                                           routing_key='*')
        #pymongo.MongoClient(mongo_ip).qa.drop_collection('REALTIMEPRO_FIX')
        self.db = pymongo.MongoClient(mongo_ip).qa.REALTIMEPRO_FIX

    def subscribe_data(self, code, frequence, data_host, data_port, data_user,
                       data_password):
        """[summary]

        Arguments:
            code {[type]} -- [description]
            frequence {[type]} -- [description]
        """

        self.sub = subscriber_topic(
            exchange='realtime_stock_{}'.format(frequence),
            host=data_host,
            port=data_port,
            user=data_user,
            password=data_password,
            routing_key='')
        for item in code:
            self.sub.add_sub(exchange='realtime_stock_{}'.format(frequence),
                             routing_key=item)
        self.sub.callback = self.callback
        self.subscriber.callback = self.callback

    def getSimStock(self, codes, frequence):
        code_list = []
        for code in codes:
            if (code.startswith('3') or code.startswith('0')):
                code_list.append('SZ' + str(code))
            elif (code.startswith('6')):
                code_list.append('SH' + str(code))

        cursor = self.db.find(
            {
                'code': {
                    '$in': code_list
                },
                "datetime": {
                    "$gte": str(datetime.date.today()),
                    "$lte": str(datetime.datetime.now())
                },
                'frequence': frequence
            }, {"_id": 0},
            batch_size=10000)

        new_list = []
        for item in cursor:
            new_list.append(self.format_stock_data(item))

        res = pd.DataFrame([item for item in new_list])
        try:
            # res['datetime'] = pd.to_datetime(res['datetime'])
            print(res)
            res = res.query('volume>1').drop_duplicates([
                'datetime', 'code'
            ]).set_index(['datetime', 'code'
                          ]).loc[:, ['open', 'high', 'low', 'close', 'volume']]
        except:
            res = None

        return res

    def upcoming_data(self, new_bar):
        """upcoming_bar :

        Arguments:
            new_bar {json} -- [description]
        """

        self._market_data = pd.concat([self._old_data.tail(200), new_bar])
        # QA.QA_util_log_info(self._market_data)

        if self.isupdate:
            self.update()
            self.isupdate = False

        self.update_account()
        # self.positions.on_price_change(float(new_bar['close']))

        #print('new_bar...',new_bar)
        self.on_bar(new_bar)

    def ind2str(self, ind, ind_type):
        z = ind.tail(1).reset_index().to_dict(orient='records')[0]
        return json.dumps({
            'topic': ind_type,
            'code': self.code,
            'type': self.frequence,
            'data': z
        })

    def callback(self, a, b, c, body):
        """在strategy的callback中,我们需要的是

        1. 更新数据
        2. 更新bar
        3. 更新策略状态
        4. 推送事件

        Arguments:
            a {[type]} -- [description]
            b {[type]} -- [description]
            c {[type]} -- [description]
            body {[type]} -- [description]
        """
        #print(body)

        new_data = json.loads(str(body, encoding='utf-8'))
        self.newbar(new_data)

    def newbar(self, new_data):

        for item in new_data:

            new_dict = self.format_stock_data(item)
            self.new_data = new_dict
            # 只接受5min
            if (not self.new_data or self.new_data['type'] != '5min'):
                # print('new_data 不存在', new_data)
                continue

            self.running_time = self.new_data['datetime']
            code = self.new_data['code']
            if code not in self.dtcode or self.dtcode[code] != str(
                    self.new_data['datetime'])[0:16]:
                # [0:16]是分钟线位数
                print('update!!!!!!!!!!!! dt:')
                self.dtcode[code] = str(self.new_data['datetime'])[0:16]
                self.isupdate = True

            self.latest_price[self.new_data['code']] = self.new_data['close']
            self.acc.on_price_change(self.new_data['code'],
                                     self.new_data['close'])
            bar = pd.DataFrame([self.new_data]).set_index(['datetime', 'code'])
            #bar = QA_DataStruct_Stock_min(bar)
            bar = bar.loc[:, ['open', 'high', 'low', 'close', 'volume']]
            #print('bar:.......',bar)
            self.upcoming_data(bar)

    def format_stock_data(self, item):
        code = item.get('code')
        new_code = code[-6:]

        d = {}
        #and item.get('frequence') == '1min'
        if new_code in self.stock_pool_list:
            d['code'] = new_code
            d['open'] = item.get('open')
            d['high'] = item.get('high')
            d['close'] = item.get('close')
            d['low'] = item.get('low')
            d['vol'] = item.get('volume')
            d['volume'] = item.get('volume')
            d['type'] = item.get('frequence')
            # d['amount'] = item.get('volume')
            d['date_stamp'] = QA_util_date_stamp(item.get('datetime'))
            d['time_stamp'] = QA_util_time_stamp(item.get('datetime'))
            d['date'] = item.get('datetime')[0:10]  # 2020-10-12
            d['datetime'] = pd.to_datetime(
                item.get('datetime'))  # 2020-10-12 10:02:00
            d['tradetime'] = item.get('datetime')[0:16]  # 2020-10-12 10:02

        return d

    def _debug_sim(self):
        self.running_mode = 'sim'

        self._old_data = QA.QA_fetch_stock_min(
            self.code,
            QA.QA_util_get_last_day(
                QA.QA_util_get_real_date(str(datetime.date.today())), 5),
            str(datetime.datetime.now()),
            format='pd',
            frequence=self.frequence).set_index(['datetime', 'code'])
        print('old:', self._old_data)
        #当天启动前行情数据
        sim_stock_df = self.getSimStock(self.code, self.frequence)
        self._old_data = pd.concat([self._old_data, sim_stock_df])

        self._old_data = self._old_data.loc[:, [
            'open', 'high', 'low', 'close', 'volume'
        ]]
        #print('old_data ;:::::::', self._old_data)
        self.database = pymongo.MongoClient(mongo_ip).QAREALTIME

        self.client = self.database.account
        self.subscriber_client = self.database.subscribe
        self.acc = QIFI_Account(username=self.strategy_id,
                                password=self.strategy_id,
                                trade_host=mongo_ip)
        print(self.acc)
        self.acc.initial()
        self.pub = publisher_routing(exchange='QAORDER_ROUTER',
                                     host=self.trade_host,
                                     port=self.trade_port,
                                     user=self.trade_user,
                                     password=self.trade_password)

        self.subscribe_data(self.code, self.frequence, self.data_host,
                            self.data_port, self.data_user, self.data_password)

        self.database.strategy_schedule.job_control.update(
            {'strategy_id': self.strategy_id}, {
                'strategy_id': self.strategy_id,
                'taskid': self.taskid,
                'filepath': os.path.abspath(__file__),
                'status': 200
            },
            upsert=True)

        # threading.Thread(target=, daemon=True).start()
        # print(self.subscribe_data)
        # self.sub.start()
        #self.debug_callback()
        self.subscriber.start()

    def debug_callback(self):
        new_data = [{
            'datetime': '2021-01-27 18:05:00',
            'updatetime': '2021-01-15 10:10:51',
            'code': 'SZ000338',
            'open': 5.24,
            'high': 5.24,
            'low': 5.24,
            'close': 5.24,
            'volume': 39378.0,
            'frequence': '5min',
            'pctchange': 0.0
        }]
        self.newbar(new_data)

        # 另一个code
        new_data = [{
            'datetime': '2021-01-27 18:05:00',
            'updatetime': '2021-01-15 10:10:51',
            'code': 'SZ000545',
            'open': 5.24,
            'high': 5.24,
            'low': 5.24,
            'close': 5.24,
            'volume': 39378.0,
            'frequence': '5min',
            'pctchange': 0.0
        }]
        self.newbar(new_data)

        new_data = [{
            'datetime': '2021-01-27 18:10:00',
            'updatetime': '2021-01-15 10:10:51',
            'code': 'SZ000338',
            'open': 5.24,
            'high': 5.24,
            'low': 5.24,
            'close': 5.24,
            'volume': 39378.0,
            'frequence': '5min',
            'pctchange': 0.0
        }]
        self.newbar(new_data)

        new_data = [{
            'datetime': '2021-01-27 18:10:00',
            'updatetime': '2021-01-15 10:10:51',
            'code': 'SZ000545',
            'open': 5.24,
            'high': 5.24,
            'low': 5.24,
            'close': 5.24,
            'volume': 39378.0,
            'frequence': '5min',
            'pctchange': 0.0
        }]
        self.newbar(new_data)

        new_data = [{
            'datetime': '2021-01-27 18:15:00',
            'updatetime': '2021-01-15 10:10:51',
            'code': 'SZ000338',
            'open': 5.24,
            'high': 5.24,
            'low': 5.24,
            'close': 5.24,
            'volume': 39378.0,
            'frequence': '5min',
            'pctchange': 0.0
        }]
        self.newbar(new_data)
        new_data = [{
            'datetime': '2021-01-27 18:15:00',
            'updatetime': '2021-01-15 10:10:51',
            'code': 'SZ000545',
            'open': 5.24,
            'high': 5.24,
            'low': 5.24,
            'close': 5.24,
            'volume': 39378.0,
            'frequence': '5min',
            'pctchange': 0.0
        }]
        self.newbar(new_data)
        '''
        new_data = [{'datetime': '2021-01-27 18:15:00', 'updatetime': '2021-01-15 10:10:51', 'code': 'SZ000338','open': 5.24,
                    'high': 5.24, 'low': 5.24, 'close': 5.24, 'volume': 39378.0, 'frequence': '5min', 'pctchange': 0.0}]
        self.newbar(new_data)
        new_data = [{'datetime': '2021-01-27 18:15:00', 'updatetime': '2021-01-15 10:10:51', 'code': 'SZ000545',
                     'open': 5.24,
                     'high': 5.24, 'low': 5.24, 'close': 5.24, 'volume': 39378.0, 'frequence': '5min',
                     'pctchange': 0.0}]
        self.newbar(new_data)

        new_data = [{'datetime': '2021-01-27 18:20:00', 'updatetime': '2021-01-15 10:10:51', 'code': 'SZ000338',
                     'open': 5.24,
                     'high': 5.24, 'low': 5.24, 'close': 5.24, 'volume': 39378.0, 'frequence': '5min',
                     'pctchange': 0.0}]
        self.newbar(new_data)
        '''

    def run(self):
        while True:
            pass

    def debug(self):
        self.running_mode = 'backtest'
        self.database = pymongo.MongoClient(mongo_ip).QUANTAXIS
        user = QA_User(username="******", password='******')
        port = user.new_portfolio(self.portfolio)
        self.acc = port.new_accountpro(account_cookie=self.strategy_id,
                                       init_cash=self.init_cash,
                                       market_type=self.market_type)
        # self.positions = self.acc.get_position(self.code)
        print('data')
        data = QA.QA_quotation(self.code,
                               self.start,
                               self.end,
                               source=QA.DATASOURCE.MONGO,
                               frequence=self.frequence,
                               market=self.market_type,
                               output=QA.OUTPUT_FORMAT.DATASTRUCT)
        print(data.data)
        data.data.apply(self.x1, axis=1)

    def update_account(self):
        if self.running_mode == 'sim':
            QA.QA_util_log_info('{} UPDATE ACCOUNT'.format(
                str(datetime.datetime.now())))

            self.accounts = self.acc.account_msg
            self.orders = self.acc.orders
            self.positions = self.acc.positions

            self.trades = self.acc.trades
            self.updatetime = self.acc.dtstr
        elif self.running_mode == 'backtest':
            # self.positions = self.acc.get_position(self.code)
            self.positions = self.acc.positions

    def send_order(
        self,
        direction='BUY',
        offset='OPEN',
        code=None,
        price=3925,
        volume=10,
        order_id='',
    ):

        towards = eval('ORDER_DIRECTION.{}_{}'.format(direction, offset))
        order_id = str(uuid.uuid4()) if order_id == '' else order_id

        if self.market_type == QA.MARKET_TYPE.STOCK_CN:
            """
            在此对于股票的部分做一些转换
            """
            if towards == ORDER_DIRECTION.SELL_CLOSE:
                towards = ORDER_DIRECTION.SELL
            elif towards == ORDER_DIRECTION.BUY_OPEN:
                towards = ORDER_DIRECTION.BUY

        if isinstance(price, float):
            pass
        elif isinstance(price, pd.Series):
            price = price.values[0]

        if self.running_mode == 'sim':

            QA.QA_util_log_info(
                '============ {} SEND ORDER =================='.format(
                    order_id))
            QA.QA_util_log_info(
                'direction{} offset {} price{} volume{}'.format(
                    direction, offset, price, volume))

            if self.check_order(direction, offset):
                self.last_order_towards = {'BUY': '', 'SELL': ''}
                self.last_order_towards[direction] = offset
                now = str(datetime.datetime.now())

                order = self.acc.send_order(code=code,
                                            towards=towards,
                                            price=price,
                                            amount=volume,
                                            order_id=order_id)
                order['topic'] = 'send_order'
                self.pub.pub(json.dumps(order), routing_key=self.strategy_id)

                self.acc.make_deal(order)
                self.bar_order['{}_{}'.format(direction, offset)] = self.bar_id
                if self.send_wx:
                    for user in self.subscriber_list:
                        QA.QA_util_log_info(self.subscriber_list)
                        try:
                            "oL-C4w2WlfyZ1vHSAHLXb2gvqiMI"
                            """http://www.yutiansut.com/signal?user_id=oL-C4w1HjuPRqTIRcZUyYR0QcLzo&template=xiadan_report&\
                                        strategy_id=test1&realaccount=133496&code=rb1910&order_direction=BUY&\
                                        order_offset=OPEN&price=3600&volume=1&order_time=20190909
                            """

                            requests.post(
                                'http://www.yutiansut.com/signal?user_id={}&template={}&strategy_id={}&realaccount={}&code={}&order_direction={}&order_offset={}&price={}&volume={}&order_time={}'
                                .format(user, "xiadan_report",
                                        self.strategy_id, self.acc.user_id,
                                        code, direction, offset, price, volume,
                                        now))
                        except Exception as e:
                            QA.QA_util_log_info(e)

            else:
                QA.QA_util_log_info('failed in ORDER_CHECK')

        elif self.running_mode == 'backtest':

            self.bar_order['{}_{}'.format(direction, offset)] = self.bar_id

            self.acc.receive_simpledeal(code=code,
                                        trade_time=self.running_time,
                                        trade_towards=towards,
                                        trade_amount=volume,
                                        trade_price=price,
                                        order_id=order_id)
Exemplo n.º 7
0
class QAStrategyCoinBase(QAStrategyCTABase):

    def __init__(self, code=['000001'], frequence='1min', strategy_id='QA_STRATEGY', risk_check_gap=1, portfolio='default',
                 start='2019-01-01', end='2019-10-21', send_wx=False, market_type='stock_cn',
                 data_host=eventmq_ip, data_port=eventmq_port, data_user=eventmq_username, data_password=eventmq_password,
                 trade_host=eventmq_ip, trade_port=eventmq_port, trade_user=eventmq_username, trade_password=eventmq_password,
                 taskid=None, mongo_ip=mongo_ip):
        super().__init__(code=code, frequence=frequence, strategy_id=strategy_id, risk_check_gap=risk_check_gap, portfolio=portfolio,
                         start=start, end=end, send_wx=send_wx,
                         data_host=eventmq_ip, data_port=eventmq_port, data_user=eventmq_username, data_password=eventmq_password,
                         trade_host=eventmq_ip, trade_port=eventmq_port, trade_user=eventmq_username, trade_password=eventmq_password,
                         taskid=taskid, mongo_ip=mongo_ip)

        self.code = code
        self.dtcode = {}
        self.send_wx = send_wx
        self.frequenceInt = 0
        '''
        self.subscriber = subscriber_topic(
            host='www.yutiansut.com',
            port='5678',
            exchange='QARealtimePro_FIX',
            durable=False,
            vhost='/',
            routing_key='*')

        '''


    def subscribe_data(self, code, frequence, data_host, data_port, data_user, data_password):
        """[summary]

        Arguments:
            code {[type]} -- [description]
            frequence {[type]} -- [description]
        """


        self.sub = subscriber_topic(exchange='realtime_stock_{}'.format(
            frequence), host=data_host, port=data_port, user=data_user, password=data_password, routing_key='')
        for item in code:
            self.sub.add_sub(exchange='realtime_stock_{}'.format(
                frequence), routing_key=item)
        self.sub.callback = self.callback
        self.subscriber.callback = self.callback


    def upcoming_data(self, new_bar):
        """upcoming_bar :

        Arguments:
            new_bar {json} -- [description]
        """
        self._market_data = pd.concat([self._old_data, new_bar])
        # QA.QA_util_log_info(self._market_data)

        if self.isupdate:
            self.update()
            self.isupdate = False

        self.update_account()
        # self.positions.on_price_change(float(new_bar['close']))
        self.on_bar(new_bar)

    def ind2str(self, ind, ind_type):
        z = ind.tail(1).reset_index().to_dict(orient='records')[0]
        return json.dumps({'topic': ind_type, 'code': self.code, 'type': self.frequence, 'data': z})

    def callback(self, a, b, c, body):
        """在strategy的callback中,我们需要的是

        1. 更新数据
        2. 更新bar
        3. 更新策略状态
        4. 推送事件

        Arguments:
            a {[type]} -- [description]
            b {[type]} -- [description]
            c {[type]} -- [description]
            body {[type]} -- [description]
        """
        print(time.strftime("%H:%M:%S", time.localtime()))
        while True:
            time_now_min = int(time.strftime("%M", time.localtime()))
            time_now_s = int(time.strftime("%S", time.localtime()))
            frequence_int = self.frequenceInt
            if (time_now_min%frequence_int == 0 and (time_now_s%30 == 0 or time_now_s%59 == 0)) :
                time.sleep(1) # 延迟1s 防止上边的if重复执行
                QA.QA_util_log_info('{} while开始....'.format(
                    str(datetime.datetime.now())))

                code_list = [huobi_SYMBOL.format(x) for x in self.code]
               
                # new_data = json.loads(str(body, encoding='utf-8'))
                lastPreMinTime = (datetime.datetime.now()).strftime(
                    "%Y-%m-%d %H:%M:%S")

                preLastPreMinTime = (datetime.datetime.now() + datetime.timedelta(minutes=-4 * frequence_int)).strftime(
                    "%Y-%m-%d %H:%M:%S")

                print(preLastPreMinTime, lastPreMinTime, self.frequence)
                self._new_data = QA.QA_fetch_cryptocurrency_min(code_list, preLastPreMinTime, lastPreMinTime, format='pd',
                                                              frequence=self.frequence)

                if (self._new_data.empty):
                    continue

                self._new_data = self._new_data.loc[:, ['code','open', 'high', 'low', 'close', 'volume','datetime']]
                #self._market_data.iloc[-1:]

                print('NEW DATA:', self._new_data)


                #整理成一个code的一个frequence为一个bar
                for idx, row in  self._new_data.iterrows():
                    #print("当前row:",row)
                    code = row['code']
                    self.latest_price[row['code']] = code

                    self.running_time = row['datetime']
                    #if self.dt != str(row['datetime'])[0:16]:
                    if code not in self.dtcode or self.dtcode[code] < str(row['datetime'])[0:16]:
                        # [0:16]是分钟线位数
                        print('update!!!!!!!!!!!!')
                        self.dtcode[code] = str(row['datetime'])[0:16]
                        self.isupdate = True


                        self.acc.on_price_change(code, row['close'])
                        bar = pd.DataFrame([row]).set_index(['datetime', 'code']).loc[:, ['open', 'high', 'low', 'close', 'volume']]
                        #print(bar)
                        self.upcoming_data(bar)

    def format_stock_data(self, item):
        code = item.get('code')
        new_code = code[-6:]
        d = {}
        #print(new_code)
        #print(item)
        import pandas as pd
        stock_pool_pd = pd.read_csv("/root/sim/stock_strategy/stock_pool.csv",encoding='utf-8',converters = {'code':str});
        stock_pool_list = stock_pool_pd['code'].tolist()
        if new_code in stock_pool_list and item.get('frequence') == '5min':
            d['code'] = new_code
            d['open'] = item.get('open')
            d['high'] = item.get('high')
            d['close'] = item.get('close')
            d['low'] = item.get('low')
            d['vol'] = item.get('volume')
            d['type'] = item.get('frequence')
            #d['amount'] = item.get('volume')
            d['date_stamp'] = QA_util_date_stamp(item.get('datetime'))
            d['time_stamp'] = QA_util_time_stamp(item.get('datetime'))
            d['date'] = item.get('datetime')[0:10] #2020-10-12
            d['datetime'] = item.get('datetime') #2020-10-12 10:02:00
            d['tradetime'] = item.get('datetime')[0:16]  #2020-10-12 10:02

        return d

    def _debug_sim(self):
        self.running_mode = 'sim'
        

        QA_SU_save_huobi_min(frequency= self.frequence, fetch_range= self.code)

        frequence_int = int(re.findall("\d+", self.frequence)[0])
        self.frequenceInt = frequence_int
        start = (datetime.datetime.now() + datetime.timedelta(minutes=-500 * frequence_int)).strftime(
            "%Y-%m-%d %H:%M:%S")
        end = (datetime.datetime.now() + datetime.timedelta(minutes=-frequence_int)).strftime(
            "%Y-%m-%d %H:%M:%S")
        code_list =  self.code
        self._old_data = QA.QA_fetch_stock_min(code_list, start, end, format='pd', frequence=self.frequence).set_index(['datetime', 'code'])

        #print(self._old_data)
        self._old_data = self._old_data.loc[:, ['open', 'high', 'low', 'close', 'volume']]

        self.database = pymongo.MongoClient(mongo_ip).QAREALTIME

        self.client = self.database.account
        self.subscriber_client = self.database.subscribe
        self.acc = QIFI_Account(
            username=self.strategy_id, password=self.strategy_id, trade_host=mongo_ip)
        self.acc.initial()
        self.pub = publisher_routing(exchange='QAORDER_ROUTER', host=self.trade_host,
                                     port=self.trade_port, user=self.trade_user, password=self.trade_password)
        '''
        self.subscribe_data(self.code, self.frequence, self.data_host,
                            self.data_port, self.data_user, self.data_password)
        '''


        self.database.strategy_schedule.job_control.update(
            {'strategy_id': self.strategy_id},
            {'strategy_id': self.strategy_id, 'taskid': self.taskid,
             'filepath': os.path.abspath(__file__), 'status': 200}, upsert=True)
        
        # threading.Thread(target=, daemon=True).start()
        #print(self.subscribe_data)
        #self.sub.start()
        #self.subscriber.start()
        self.callback(1,2,3,4)

    def run(self):
        while True:
            pass


    def debug(self):
        self.running_mode = 'backtest'
        self.database = pymongo.MongoClient(mongo_ip).QUANTAXIS
        user = QA_User(username="******", password='******')
        port = user.new_portfolio(self.portfolio)
        self.acc = port.new_accountpro(
            account_cookie=self.strategy_id, init_cash=self.init_cash, market_type=self.market_type)
        #self.positions = self.acc.get_position(self.code)


        data = QA.QA_quotation(self.code, self.start, self.end, source=QA.DATASOURCE.MONGO,
                               frequence=self.frequence, market=self.market_type, output=QA.OUTPUT_FORMAT.DATASTRUCT)
        #print(data.data)
        data.data.apply(self.x1, axis=1)

    def update_account(self):
        if self.running_mode == 'sim':
            QA.QA_util_log_info('{} UPDATE ACCOUNT'.format(
                str(datetime.datetime.now())))

            self.accounts = self.acc.account_msg
            self.orders = self.acc.orders
            self.positions = self.acc.positions

            self.trades = self.acc.trades
            self.updatetime = self.acc.dtstr
        elif self.running_mode == 'backtest':
            #self.positions = self.acc.get_position(self.code)
            self.positions = self.acc.positions

    def send_order(self,  direction='BUY', offset='OPEN', code=None, price=3925, volume=10, order_id='',):

        towards = eval('ORDER_DIRECTION.{}_{}'.format(direction, offset))
        order_id = str(uuid.uuid4()) if order_id == '' else order_id

        if self.market_type == QA.MARKET_TYPE.STOCK_CN:
            """
            在此对于股票的部分做一些转换
            """
            if towards == ORDER_DIRECTION.SELL_CLOSE:
                towards = ORDER_DIRECTION.SELL
            elif towards == ORDER_DIRECTION.BUY_OPEN:
                towards = ORDER_DIRECTION.BUY

        if isinstance(price, float):
            pass
        elif isinstance(price, pd.Series):
            price = price.values[0]

        if self.running_mode == 'sim':

            QA.QA_util_log_info(
                '============ {} SEND ORDER =================='.format(order_id))
            QA.QA_util_log_info('direction{} offset {} price{} volume{}'.format(
                direction, offset, price, volume))

            if self.check_order(direction, offset, code):
                self.last_order_towards = {'BUY': '', 'SELL': ''}
                self.last_order_towards[direction] = offset
                now = str(datetime.datetime.now())

                order = self.acc.send_order(
                    code=code, towards=towards, price=price, amount=volume, order_id=order_id)
                order['topic'] = 'send_order'
                self.pub.pub(
                    json.dumps(order), routing_key=self.strategy_id)

                self.acc.make_deal(order)
                self.bar_order['{}_{}'.format(direction, offset)] = self.bar_id
                if self.send_wx:
                    for user in self.subscriber_list:
                        QA.QA_util_log_info(self.subscriber_list)
                        try:
                            "oL-C4w2WlfyZ1vHSAHLXb2gvqiMI"
                            """http://www.yutiansut.com/signal?user_id=oL-C4w1HjuPRqTIRcZUyYR0QcLzo&template=xiadan_report&\
                                        strategy_id=test1&realaccount=133496&code=rb1910&order_direction=BUY&\
                                        order_offset=OPEN&price=3600&volume=1&order_time=20190909
                            """

                            requests.post('http://www.yutiansut.com/signal?user_id={}&template={}&strategy_id={}&realaccount={}&code={}&order_direction={}&order_offset={}&price={}&volume={}&order_time={}'.format(
                                user, "xiadan_report", self.strategy_id, self.acc.user_id, code, direction, offset, price, volume, now))
                        except Exception as e:
                            QA.QA_util_log_info(e)

            else:
                QA.QA_util_log_info('failed in ORDER_CHECK')

        elif self.running_mode == 'backtest':

            self.bar_order['{}_{}'.format(direction, offset)] = self.bar_id

            self.acc.receive_simpledeal(
                code=code, trade_time=self.running_time, trade_towards=towards, trade_amount=volume, trade_price=price, order_id=order_id)