Esempio n. 1
0
    def context_setting(self):
        """
        API trading and quote context setting
        :returns: trade context, quote context
        """
        if self.unlock_password == "":
            raise Exception("请先配置交易解锁密码! password: {}".format(
                self.unlock_password))

        quote_ctx = ft.OpenQuoteContext(host=self.api_svr_ip,
                                        port=self.api_svr_port)

        if 'HK.' in self.stock:
            trade_ctx = ft.OpenHKTradeContext(host=self.api_svr_ip,
                                              port=self.api_svr_port)

            if self.trade_env == ft.TrdEnv.REAL:
                ret_code, ret_data = trade_ctx.unlock_trade(
                    self.unlock_password)
                if ret_code == ft.RET_OK:
                    print('解锁交易成功!')
                else:
                    raise Exception("请求交易解锁失败: {}".format(ret_data))
            else:
                print('解锁交易成功!')
        elif 'US.' in self.stock:
            if self.trade_env != 0:
                raise Exception("美股交易接口不支持仿真环境 trade_env: {}".format(
                    self.trade_env))
            trade_ctx = ft.OpenUSTradeContext(host=self.api_svr_ip,
                                              port=self.api_svr_port)
        else:
            raise Exception("stock输入错误 stock: {}".format(self.stock))

        return quote_ctx, trade_ctx
Esempio n. 2
0
    def connectTrade(self):
        """连接交易功能"""
        # 连接交易接口
        if self.market == 'US':
            self.tradeCtx = ft.OpenUSTradeContext(self.host, self.port)
            OrderHandlerBase = USTradeOrderHandlerBase
            DealHandlerBase = USTradeDealHandlerBase
        else:
            self.tradeCtx = ft.OpenHKTradeContext(self.host, self.port)
            OrderHandlerBase = HKTradeOrderHandlerBase
            DealHandlerBase = HKTradeDealHandlerBase

        # 继承实现处理器类
        class OrderHandler(OrderHandlerBase):
            """委托处理器"""
            gateway = self  # 缓存Gateway对象

            def on_recv_rsp(self, rsp_str):
                ret_code, content = super(OrderHandler,
                                          self).on_recv_rsp(rsp_str)
                if ret_code != RET_OK:
                    return RET_ERROR, content
                self.gateway.processOrder(content)
                return RET_OK, content

        class DealHandler(DealHandlerBase):
            """订单簿处理器"""
            gateway = self

            def on_recv_rsp(self, rsp_str):
                ret_code, content = super(DealHandler,
                                          self).on_recv_rsp(rsp_str)
                if ret_code != RET_OK:
                    return RET_ERROR, content
                self.gateway.processDeal(content)
                return RET_OK, content

        # 只有港股实盘交易才需要解锁
        if self.market == 'HK' and self.env == 0:
            self.tradeCtx.unlock_trade(self.password)

        # 设置回调处理对象
        self.tradeCtx.set_handler(OrderHandler())
        self.tradeCtx.set_handler(DealHandler())

        # 启动交易接口
        self.tradeCtx.start()

        # 订阅委托推送
        self.tradeCtx.subscribe_order_deal_push([],
                                                order_deal_push=True,
                                                envtype=self.env)

        self.writeLog(u'交易接口连接成功')
Esempio n. 3
0
    def test_maxReqPerSec_deal_list_query(self):
        trade_ctx = futuquant.OpenHKTradeContext(host='127.0.0.1', port=11111)
        trade_ctx.unlock_trade(password='******')

        req_times_succ = 0
        req_times_total = 0
        t_start = time.time()
        while time.time() <= (t_start + 1):
            ret_code, ret_data = trade_ctx.deal_list_query()
            req_times_total += 1
            if ret_code is RET_OK:
                req_times_succ += 1
            else:
                self.logger.info('deal_list_query req_times_total = ' +
                                 str(req_times_total) + ' ret_code = ' +
                                 str(ret_code) + ' ret_data = ' + ret_data)
        trade_ctx.close()
        self.logger.info('deal_list_query req_times_total = ' +
                         str(req_times_total) + ' req_times_succ = ' +
                         str(req_times_succ))
Esempio n. 4
0
    def _process_init_api(self):
        if type(self._quote_ctx) != int or type(self._trade_ctx) != int:
            return

        # 创建futu api对象
        if self._quote_ctx == 0:
            self._quote_ctx = ft.OpenQuoteContext(self._api_ip, self._api_port)
        if self._trade_ctx == 0:
            if self._market == MARKET_HK:
                self._trade_ctx = ft.OpenHKTradeContext(
                    self._api_ip, self._api_port)
            elif self._market == MARKET_US:
                self._trade_ctx = ft.OpenUSTradeContext(
                    self._api_ip, self._api_port)
            else:
                raise Exception("error param!")

        if self._env_type == ft.TrdEnv.REAL:
            ret, _ = self._trade_ctx.unlock_trade(self._trade_password)
            if 0 != ret:
                raise Exception("error param!")

        # 开始futu api异步数据推送
        self._quote_ctx.start()
        self._trade_ctx.start()

        # 市场状态检查
        self._check_market_event = FutuMarketEvent(self._market,
                                                   self._quote_ctx,
                                                   self._event_engine)

        #定阅行情数据
        self._futu_data_event = FutuDataEvent(self, self._quote_ctx,
                                              self._event_engine,
                                              self._tiny_strate.symbol_pools)

        # 启动事件
        self._tiny_strate.on_start()
def make_order_and_cancel(api_svr_ip, api_svr_port, unlock_password, test_code, trade_env, acc_id):
    """
    使用请先配置正确参数:
    :param api_svr_ip: (string) ip
    :param api_svr_port: (string) ip
    :param unlock_password: (string) 交易解锁密码, 必需修改!
    :param test_code: (string) 股票
    :param trade_env:  参见 ft.TrdEnv的定义
    :param acc_id:  交易子账号id
    """
    if unlock_password == "":
        raise Exception("请先配置交易解锁密码!")

    quote_ctx = ft.OpenQuoteContext(host=api_svr_ip, port=api_svr_port)  # 创建行情api
    quote_ctx.subscribe(test_code, ft.SubType.ORDER_BOOK) # 定阅摆盘

    # 创建交易api
    is_hk_trade = 'HK.' in test_code
    if is_hk_trade:
        trade_ctx = ft.OpenHKTradeContext(host=api_svr_ip, port=api_svr_port)
    else:
        trade_ctx = ft.OpenUSTradeContext(host=api_svr_ip, port=api_svr_port)

    # 每手股数
    lot_size = 0
    is_unlock_trade = False
    is_fire_trade = False
    while not is_fire_trade:
        sleep(2)
        # 解锁交易
        if not is_unlock_trade and trade_env == ft.TrdEnv.REAL:
            print("unlocking trade...")
            ret_code, ret_data = trade_ctx.unlock_trade(unlock_password)
            is_unlock_trade = (ret_code == ft.RET_OK)
            if not is_unlock_trade:
                print("请求交易解锁失败:{}".format(ret_data))
                break

        if lot_size == 0:
            print("get lotsize...")
            ret, data = quote_ctx.get_market_snapshot(test_code)
            lot_size = data.iloc[0]['lot_size'] if ret == ft.RET_OK else 0
            if ret != ft.RET_OK:
                print("取不到每手信息,重试中: {}".format(data))
                continue
            elif lot_size <= 0:
                raise BaseException("该股票每手信息错误,可能不支持交易 code ={}".format(test_code))

        print("get order book...")
        ret, data = quote_ctx.get_order_book(test_code)  # 得到第十档数据
        if ret != ft.RET_OK:
            continue

        # 计算交易价格
        bid_order_arr = data['Bid']
        if is_hk_trade:
            if len(bid_order_arr) != 10:
                continue
            # 港股下单: 价格定为第十档
            price, _, _ = bid_order_arr[9]
        else:
            if len(bid_order_arr) == 0:
                continue
            # 美股下单: 价格定为一档降10%
            price, _, _ = bid_order_arr[0]
            price = round(price * 0.9, 2)

        qty = lot_size

        # 价格和数量判断
        if qty == 0 or price == 0.0:
            continue

        # 下单
        order_id = 0
        print("place order : price={} qty={} code={}".format(price, qty, test_code))
        ret_code, ret_data = trade_ctx.place_order(price=price, qty=qty, code=test_code, trd_side=ft.TrdSide.BUY,
                                                   order_type=ft.OrderType.NORMAL, trd_env=trade_env, acc_id=acc_id)
        is_fire_trade = True
        print('下单ret={} data={}'.format(ret_code, ret_data))
        if ret_code == ft.RET_OK:
            row = ret_data.iloc[0]
            order_id = row['order_id']

        # 循环撤单
        sleep(2)


        if order_id:
            while True:
                ret_code, ret_data = trade_ctx.order_list_query(order_id=order_id, status_filter_list=[], code='',
                                                                start='', end='', trd_env=trade_env, acc_id=acc_id)

                if ret_code != ft.RET_OK:
                    sleep(2)
                    continue
                order_status = ret_data.iloc[0]['order_status']
                if order_status in [ft.OrderStatus.SUBMIT_FAILED, ft.OrderStatus.TIMEOUT, ft.OrderStatus.FILLED_ALL,
                                    ft.OrderStatus.FAILED, ft.OrderStatus.DELETED]:
                    break

                print("cancel order...")
                ret_code, ret_data = trade_ctx.modify_order(modify_order_op=ft.ModifyOrderOp.CANCEL, order_id=order_id,
                                price=price, qty=qty, adjust_limit=0, trd_env=trade_env, acc_id=acc_id)
                print("撤单ret={} data={}".format(ret_code, ret_data))
                if ret_code == ft.RET_OK:
                    break
                else:
                    sleep(2)
    # destroy object
    quote_ctx.close()
    trade_ctx.close()
        return RET_OK, content


if __name__ == '__main__':

    ip = '127.0.0.1'
    port = 22221
    quote_all = {}
    tick_data = {}
    code = 'HK.00123'
    unlock_pwd = '887886'
    trd_env = ft.TrdEnv.SIMULATE
    order_type = ft.OrderType.SPECIAL_LIMIT

    quote_ctx = ft.OpenQuoteContext(ip, port)
    trd_ctx = ft.OpenHKTradeContext(ip, port)
    # 获取登录账号信息
    user_info = np.loadtxt('user_info.txt', dtype=str, delimiter=',')

    # 登录账户
    clientId = tda.login(user_info[0], user_info[1], user_info[2],
                         user_info[3], user_info[4], user_info[5],
                         user_info[6], user_info[7])
    if clientId == 0:
        print "账户登录成功"
    else:
        print "账户登录失败,请检查登录信息"

    # data = xlrd.open_workbook('d:/monitor_harden.xlsx')
    # table = data.sheets()[1]#通过索引顺序获取
    # col=table.col_values(0);
Esempio n. 7
0
quote_ctx.get_stock_basicinfo(market, stock_type='STOCK')             # 获取股票信息
quote_ctx.get_history_kline(code, start=None, end=None, ktype='K_DAY', autype='qfq')  # 获取历史K线
quote_ctx.get_autype_list(code_list)                                  # 获取复权因子
quote_ctx.get_market_snapshot(code_list)                              # 获取市场快照
quote_ctx.get_plate_list(market, plate_class)                         # 获取板块集合下的子板块列表
quote_ctx.get_plate_stock(market, stock_code)                         # 获取板块下的股票列表

# 高频数据接口
quote_ctx.get_stock_quote(code_list) # 获取报价
quote_ctx.get_rt_ticker(code, num)   # 获取逐笔
quote_ctx.get_cur_kline(code, num, ktype=' K_DAY', autype='qfq') # 获取当前K线
quote_ctx.get_order_book(code)       # 获取摆盘
quote_ctx.get_rt_data(code)          # 获取分时数据
quote_ctx.get_broker_queue(code)     # 获取经纪队列


# 实例化港股交易上下文对象
trade_hk_ctx = ft.OpenHKTradeContext(host="127.0.0.1", port=11111)

# 实例化美股交易上下文对象
trade_us_ctx = ft.OpenUSTradeContext(host="127.0.0.1", port=11111)

# 交易接口列表
ret_code, ret_data = trade_hk_ctx.unlock_trade(password='******')                # 解锁接口
ret_code, ret_data = trade_hk_ctx.place_order(price, qty, strcode, orderside, ordertype=0, envtype=0) # 下单接口
ret_code, ret_data = trade_hk_ctx.set_order_status(status, orderid=0, envtype=0) # 设置订单状态
ret_code, ret_data = trade_hk_ctx.change_order(price, qty, orderid=0, envtype=0) # 修改订单
ret_code, ret_data = trade_hk_ctx.accinfo_query(envtype=0)                       # 查询账户信息
ret_code, ret_data = trade_hk_ctx.order_list_query(statusfilter="", envtype=0)   # 查询订单列表
ret_code, ret_data = trade_hk_ctx.position_list_query(envtype=0)                 # 查询持仓列表
ret_code, ret_data = trade_hk_ctx.deal_list_query(envtype=0)                     # 查询成交列表
Esempio n. 8
0
 def __init__(self):
     self.trd_ctx = ft.OpenHKTradeContext(host='127.0.0.1', port=11111)
Esempio n. 9
0
def trailing_stop(api_svr_ip='127.0.0.1',
                  api_svr_port=11111,
                  unlock_password="",
                  code='HK.00700',
                  trade_env=ft.TrdEnv.SIMULATE,
                  method=TrailingMethod.DROP_ABS,
                  drop=1.0,
                  volume=100,
                  how_to_sell=SellMethod.SMART_SELL,
                  diff=0,
                  rest_time=2,
                  enable_email_notification=False,
                  receiver=''):
    """
    止损策略函数
    :param api_svr_ip: (string)ip
    :param api_svr_port: (int)port
    :param unlock_password: (string)交易解锁密码, 必需修改! 模拟交易设为一个非空字符串即可
    :param code: (string)股票
    :param trade_env: ft.TrdEnv.REAL: 真实交易 ft.TrdEnv.SIMULATE: 模拟交易
    :param method: method == TrailingMethod.DROP_ABS: 股票下跌drop价格就会止损  railingMethod.DROP_PER: 股票下跌drop的百分比就会止损
    :param drop: method == TrailingMethod.DROP_ABS, 股票下跌的价格   method == TrailingMethod.DROP_PER,股票下跌的百分比,0.01表示下跌1%则止损
    :param volume: 需要卖掉的股票数量
    :param how_to_sell: 以何种方式卖出股票, SellMethod 类型
    :param diff: 默认为0,当how_to_sell为SellMethod.DROP_ABS时,以(市价-diff)的价格卖出
    :param rest_time: 每隔REST_TIME秒,会检查订单状态, 需要>=2
    :param enable_email_notification: 激活email功能
    :param receiver: 邮件接收者
    """
    EmailNotification.set_enable(enable_email_notification)

    if how_to_sell not in [SellMethod.SIMPLE_SELL, SellMethod.SMART_SELL]:
        raise Exception('how_to_sell value error')

    if method not in [TrailingMethod.DROP_ABS, TrailingMethod.DROP_PER]:
        raise Exception('method value error')

    quote_ctx = ft.OpenQuoteContext(host=api_svr_ip, port=api_svr_port)
    is_hk_trade = 'HK.' in code
    if is_hk_trade:
        trade_ctx = ft.OpenHKTradeContext(host=api_svr_ip, port=api_svr_port)
    else:
        trade_ctx = ft.OpenUSTradeContext(host=api_svr_ip, port=api_svr_port)

    if unlock_password == "":
        raise Exception('请先配置交易密码')

    ret, data = trade_ctx.unlock_trade(unlock_password)
    if ret != ft.RET_OK:
        raise Exception('解锁交易失败')

    ret, data = trade_ctx.position_list_query(trd_env=trd_env)
    if ret != ft.RET_OK:
        raise Exception("无法获取持仓列表")

    try:
        qty = data[data['code'] == code].iloc[0]['qty']
    except:
        raise Exception('你没有持仓!无法买卖')

    qty = int(qty)
    if volume == 0:
        volume = qty
    if volume < 0:
        raise Exception('volume lower than  0')
    elif qty < volume:
        raise Exception('持仓不足')

    ret, data = quote_ctx.get_market_snapshot(code)
    if ret != ft.RET_OK:
        raise Exception('获取lot size失败')
    lot_size = data.iloc[0]['lot_size']

    if volume % lot_size != 0:
        raise Exception('volume 必须是{}的整数倍'.format(lot_size))

    ret, data = quote_ctx.subscribe(code, ft.SubType.QUOTE)
    if ret != ft.RET_OK:
        raise Exception('订阅QUOTE错误: error {}:{}'.format(ret, data))

    ret, data = quote_ctx.subscribe(code, ft.SubType.ORDER_BOOK)
    if ret != ft.RET_OK:
        print('error {}:{}'.format(ret, data))
        raise Exception('订阅order book失败: error {}:{}'.format(ret, data))

    if diff:
        if is_hk_trade:
            ret, data = quote_ctx.get_order_book(code)
            if ret != ft.RET_OK:
                raise Exception(
                    '获取order book失败: cannot get order book'.format(data))

            min_diff = round(abs(data['Bid'][0][0] - data['Bid'][1][0]), 3)
            if floor(diff / min_diff) * min_diff != diff:
                raise Exception('diff 应是{}的整数倍'.format(min_diff))
        else:
            if round(diff, 2) != diff:
                raise Exception('美股价差保留2位小数{}->{}'.format(
                    diff, round(diff, 2)))

    if method == TrailingMethod.DROP_ABS:
        if is_hk_trade:
            if floor(drop / min_diff) * min_diff != drop:
                raise Exception('drop必须是{}的整数倍'.format(min_diff))
        else:
            if round(drop, 2) != drop:
                raise Exception('drop必须保留2位小数{}->{}'.format(
                    drop, round(drop, 2)))

    elif method == TrailingMethod.DROP_PER:
        if drop < 0 or drop > 1:
            raise Exception('drop must in [0, 1] if method is DROP_PER')

    trailing_stop_handler = TrailingStopHandler(quote_ctx, is_hk_trade, method,
                                                drop)
    quote_ctx.set_handler(trailing_stop_handler)
    quote_ctx.start()
    while True:
        if trailing_stop_handler.finished:
            # sell the stock
            qty = volume
            sell_price = trailing_stop_handler.stop
            while qty > 0:
                if how_to_sell == SellMethod.SIMPLE_SELL:
                    data = simple_sell(quote_ctx, trade_ctx, code,
                                       sell_price - diff, qty, trade_env,
                                       ft.OrderType.SPECIAL_LIMIT)
                else:
                    data = smart_sell(quote_ctx, trade_ctx, code, qty,
                                      trade_env, ft.OrderType.SPECIAL_LIMIT)
                if data is None:
                    print('下单失败')
                    EmailNotification.send_email(
                        receiver, '下单失败', '股票代码{},数量{}'.format(code, volume))
                    sleep(rest_time)
                    continue

                order_id = data.iloc[0]['order_id']
                sleep(rest_time)

                while True:
                    ret, data = trade_ctx.order_list_query(order_id=order_id,
                                                           trd_env=trade_env)
                    if ret != ft.RET_OK:
                        sleep(rest_time)
                        continue

                    status = data.iloc[0]['order_status']
                    dealt_qty = int(data.iloc[0]['dealt_qty'])
                    order_price = data.iloc[0]['price']
                    qty -= dealt_qty

                    if status == ft.OrderStatus.FILLED_ALL:
                        print('全部成交:股票代码{}, 成交总数{},价格{}'.format(
                            code, dealt_qty, order_price))
                        EmailNotification.send_email(
                            receiver, '全部成交', '股票代码{},成交总数{},价格{}'.format(
                                code, dealt_qty, order_price))
                        break
                    elif status == ft.OrderStatus.FILLED_PART:
                        print('部分成交:股票代码{},成交总数{},价格{}'.format(
                            code, dealt_qty, order_price))
                        EmailNotification.send_email(
                            receiver, '部分成交', '股票代码{},成交总数{},价格{}'.format(
                                code, dealt_qty, order_price))
                        break
                    elif status == ft.OrderStatus.FAILED or status == ft.OrderStatus.SUBMIT_FAILED or \
                                    status == ft.OrderStatus.CANCELLED_ALL or status == ft.OrderStatus.DELETED:
                        break
                    else:
                        trade_ctx.modify_order(ft.ModifyOrderOp.CANCEL,
                                               order_id, 0, 0)
                        sleep(rest_time)
                        continue

                if how_to_sell == SellMethod.SIMPLE_SELL:
                    ret, data = quote_ctx.get_order_book(code)
                    if ret != ft.RET_OK:
                        raise Exception('获取order_book失败')
                    sell_price = data['Bid'][0][0]

            # draw price and stop
            price_lst = trailing_stop_handler.price_lst
            plt.plot(np.arange(len(price_lst)), price_lst)
            stop_list = trailing_stop_handler.stop_lst
            plt.plot(np.arange(len(stop_list)), stop_list)
            break

    quote_ctx.close()
    trade_ctx.close()