Exemple #1
0
 def update_ctp_order(cls,
                      account_name,
                      pOrder,
                      session_id=None,
                      front_id=None):
     complete_time = cancel_time = None
     if pOrder.VolumeTotal == 0:
         complete_time = datetime.now().strftime("%Y-%m-%dT%H:%M:%S")
     if pOrder.OrderStatus == ApiStruct.OST_Canceled:
         cancel_time = datetime.now().strftime("%Y-%m-%dT%H:%M:%S")
     update_time = datetime.now().strftime("%Y-%m-%dT%H:%M:%S")
     finished = bool(complete_time or cancel_time)
     session_id = session_id or pOrder.SessionID
     front_id = front_id or pOrder.FrontID
     data = {
         "Account": account_name,
         "BrokerID": pOrder.BrokerID.decode(),
         "InvestorID": pOrder.InvestorID.decode(),
         "session_id": session_id,
         "front_id": front_id,
         'order_ref': pOrder.OrderRef.decode(),
         "OrderSysID": pOrder.OrderSysID.decode().strip(),
         "InstrumentID": pOrder.InstrumentID.decode(),
         "Direction": pOrder.Direction.decode(),
         "Offset": pOrder.CombOffsetFlag.decode(),
         "Price": pOrder.LimitPrice,
         "VolumesTotal": pOrder.VolumeTotalOriginal,
         'VolumesTraded': pOrder.VolumeTraded,
         'UpdateTime': update_time,
         'CompleteTime': complete_time,
         'CancelTime': cancel_time,
         'StatusMsg': pOrder.StatusMsg.decode("gbk"),
         'Finished': finished,
     }
     api.action("ctp_order", "partial_update", params=data)
Exemple #2
0
 def submit(self, order_id):
     # 把任务状态设置为“已运行”
     api.action("order",
                "partial_update",
                params={
                    "ID": order_id,
                    "Status": 1
                })
     # 正式开始发单
     asyncio.ensure_future(self.trade(order_id), loop=self.loop)
Exemple #3
0
 async def trade(self, order_id, retries=20):
     if retries == 0:
         logger.info(f"{order_id}尝试达到最大次数,停止。")
         api.action("order",
                    "partial_update",
                    params={
                        "ID":
                        order_id,
                        "Status":
                        OrderStatus.FINISHED,
                        "StatusMsg":
                        "尝试达到最大次数",
                        "CancelTime":
                        datetime.now().strftime("%Y-%m-%dT%H:%M:%S")
                    })
         return
     task = self.get_task(order_id)
     if task['Status'] == OrderStatus.FINISHED:
         return
     trade_volume, offset = self.decide_volume_and_offset(task)
     if not trade_volume:
         return
     price = self.decide_price(task['InstrumentID'], task['Direction'],
                               task['Price'])
     sessionid, frontid, orderref = self.trader.send_order(
         task['InstrumentID'], price, trade_volume, task['Direction'],
         offset, order_id)
     await asyncio.sleep(task['split_options']['sleep_after_submit'],
                         loop=self.loop)
     ctp_order = TradingAPI.get_ctp_order(sessionid, frontid, orderref)
     if not hasattr(ctp_order, "Finished"):
         print(ctp_order)
     if not ctp_order['Finished']:
         self.trader.cancel_order(task['InstrumentID'], orderref, frontid,
                                  sessionid)
     if ctp_order.get('CancelTime'):
         # 如果CTP发单出错,那么直接取消整个订单
         api.action("order",
                    "partial_update",
                    params={
                        "ID":
                        order_id,
                        "Status":
                        OrderStatus.FINISHED,
                        "StatusMsg":
                        ctp_order['StatusMsg'],
                        "CancelTime":
                        datetime.now().strftime("%Y-%m-%dT%H:%M:%S")
                    })
         return
     await asyncio.sleep(task['split_options']['sleep_after_cancel'],
                         loop=self.loop)
     await self.trade(order_id, retries - 1)
Exemple #4
0
 def insert_ctp_trade(account, pTrade):
     data = {
         "CTPOrderID": 123456,  # This is dummy
         "OrderSysID": pTrade.OrderSysID.decode().strip(),
         "Account": account,
         "Instrument": pTrade.InstrumentID.decode(),
         "Direction": pTrade.Direction.decode(),
         "OffsetFlag": pTrade.OffsetFlag.decode(),
         "TradeID": pTrade.TradeID.decode(),
         "Price": pTrade.Price,
         "Volume": pTrade.Volume,
         "TradeTime": reformat_date(pTrade.TradeDate, pTrade.TradeTime)
     }
     api.action("ctp_trade", "create", params=data)
Exemple #5
0
    def send_order(self, instrument, price, volume, direction, offset,
                   order_id):
        orderref = str(self.inc_orderref_id())
        instrument_info = api.action("instruments",
                                     "read",
                                     params={"InstrumentID": instrument})
        order = ApiStruct.InputOrderField(
            BrokerID=self.broker_id,
            InvestorID=self.investor_id,
            InstrumentID=instrument,
            OrderRef=orderref,
            UserID=self.investor_id,
            OrderPriceType=ApiStruct.OPT_LimitPrice,
            LimitPrice=price,
            VolumeTotalOriginal=volume,
            Direction=direction,
            CombOffsetFlag=offset,
            CombHedgeFlag=ApiStruct.HF_Speculation,
            ContingentCondition=ApiStruct.CC_Immediately,
            ForceCloseReason=ApiStruct.FCC_NotForceClose,
            IsAutoSuspend=0,
            TimeCondition=ApiStruct.TC_GFD,
            UserForceClose=0,
            VolumeCondition=ApiStruct.VC_AV,
            MinVolume=1,
            ExchangeID=instrument_info['ExchangeID'],
        )

        # 插入API必须在CTP报单之前,否则OnRtnOrder时可能查询不到报单
        TradingAPI.insert_ctp_order(self.account_name, order_id, order,
                                    self.session_id, self.front_id)

        self.ReqOrderInsert(order, self.inc_request_id())

        return self.session_id, self.front_id, orderref
Exemple #6
0
 def get_order(order_id):
     order = api.action("order", "read", params={"ID": order_id})
     order['split_options'] = {
         "sleep_after_submit": order['SplitSleepAfterSubmit'],
         "sleep_after_cancel": order['SplitSleepAfterCancel'],
         "split_percent": order['SplitPercent'],
     }
     return order
Exemple #7
0
 def get_ctp_order(sessionid, frontid, orderref):
     return api.action("ctp_order",
                       "read",
                       params={
                           "session_id": sessionid,
                           "front_id": frontid,
                           "order_ref": orderref
                       })
Exemple #8
0
 def query_order(orderref):
     rsp = api.action("query_order_from_ctporder",
                      "read",
                      params={"id": int(orderref)})
     if rsp:
         return rsp['OrderID']
     else:
         raise ValueError(f"Can't find CTPOrder {orderref}")
Exemple #9
0
 def __init__(self, account_name):
     self.account_name = account_name
     self.url = self.register(account_name)
     atexit.register(lambda: api.action(
         "tradebot", "delete", params={"id": account_name}))
     self.loop = None
     self.trader = TraderBot(account_name)
     self.trader.start()
     self.task_manager = TaskManager(self.trader)
Exemple #10
0
 def insert_ctp_order(account, order_id, pInputOrder, session_id, front_id):
     data = {
         "SessionID": session_id,
         "OrderRef": pInputOrder.OrderRef.decode(),
         "FrontID": front_id,
         "Account": account,
         "BrokerID": pInputOrder.BrokerID.decode(),
         "InvestorID": pInputOrder.InvestorID.decode(),
         "OrderID": order_id,
         "InstrumentID": pInputOrder.InstrumentID.decode(),
         "Direction": pInputOrder.Direction.decode(),
         "Offset": pInputOrder.CombOffsetFlag.decode(),
         "Price": pInputOrder.LimitPrice,
         "VolumesTotal": pInputOrder.VolumeTotalOriginal,
         "VolumesTraded": 0,
         "InsertTime": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
         "Finished": False,
     }
     api.action("ctp_order", "create", params=data)
Exemple #11
0
 def decide_volume_and_offset(self, task):
     if task['Offset'] == ApiStruct.OF_Close:
         # 处理平仓,优先平昨
         if task['Direction'] == ApiStruct.D_Buy:
             cs = 'S'
         else:
             cs = 'L'
         position = TraderInterface.query_position(self.trader.account_name,
                                                   task['InstrumentID'])
         # 优先使用昨仓
         volumes_holding = position.get(f'Yd{cs}Position', 0)
         offset = ApiStruct.OF_CloseYesterday
         if not volumes_holding:
             # 如果没有昨仓,使用今仓
             volumes_holding = position.get(f'Today{cs}Position', 0)
             offset = ApiStruct.OF_CloseToday
         if not volumes_holding:
             # 如果已经没有仓位了,取消整个订单
             api.action("order",
                        "partial_update",
                        params={
                            "ID":
                            task['ID'],
                            "Status":
                            OrderStatus.FINISHED,
                            "StatusMsg":
                            "平仓数量不够",
                            "CancelTime":
                            datetime.now().strftime("%Y-%m-%dT%H:%M:%S")
                        })
             return 0, None
     else:
         # 如果开仓,不限数量
         volumes_holding = 99999999999
         offset = task['Offset']
     volumes_left = max(
         min(task['VolumesTotal'] - task['VolumesTraded'], volumes_holding),
         0)
     percent = task['split_options']['split_percent']
     volume = min(max(round(percent * volumes_left), 1), volumes_left)
     return volume, offset
Exemple #12
0
 def __init__(self, account_name):
     self.account_name = account_name
     account_info = api.action("ctp", "read", params={"Name": account_name})
     print(account_info)
     self.position_detail_cache = {}
     super().__init__(
         account_info['TdHost'],
         account_info['UserID'],
         account_info['BrokerID'],
         account_info['Password'],
         account_info['AppID'],
         account_info['AuthCode'],
     )
Exemple #13
0
 def register(self, account):
     if platform.system() == "Windows":
         params = {
             "account": account,
             "method": "tcp",
             "bind": "127.0.0.1",
         }
     else:
         params = {"account": account}
     resp = api.action("tradebot", "create", params=params)
     if not resp['OK']:
         raise RuntimeError(
             f"Tradebot with account {account} is already running")
     return resp['url']
Exemple #14
0
 def insert_order(account, instrument, price, volume, direction, offset,
                  split_options):
     data = {
         "Account": account,
         "InstrumentID": instrument,
         "Direction": direction,
         "Offset": offset,
         "Price": str(price),
         "VolumesTotal": volume,
         "VolumesTraded": 0,
         "InsertTime": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
         "SplitSleepAfterSubmit": split_options['sleep_after_submit'],
         "SplitSleepAfterCancel": split_options['sleep_after_cancel'],
         "SplitPercent": split_options['split_percent'],
         "Status": OrderStatus.INACTIVE,
     }
     resp = api.action("order", "create", params=data)
     return resp['ID']
Exemple #15
0
    async def run(self):
        # 第一次先启动所有“已运行”的任务,然后只轮询“未启动”的任务
        status_flag = OrderStatus.RUNNING

        while True:
            resp = api.action("order",
                              "list",
                              params={
                                  "Status": status_flag,
                                  "Account": self.trader.account_name
                              })
            for order in resp:
                logger.info(
                    f"启动任务 {order['ID']} {order['InstrumentID']} {order['Direction']} {order['VolumesTotal'] - order['VolumesTraded']} @ {order['Price']}"
                )
                self.submit(order['ID'])
            await asyncio.sleep(1, loop=self.loop)
            status_flag = OrderStatus.INACTIVE
Exemple #16
0
 def cancel_order(self, instrument, order_ref, front_id, session_id):
     """
     撤单
     """
     instrument_info = api.action("instruments",
                                  "read",
                                  params={"InstrumentID": instrument})
     req = ApiStruct.InputOrderActionField(
         InstrumentID=instrument,
         OrderRef=order_ref,
         FrontID=front_id,
         SessionID=session_id,
         ActionFlag=ApiStruct.AF_Delete,
         BrokerID=self.broker_id,
         InvestorID=self.investor_id,
         UserID=self.investor_id,
         ExchangeID=instrument_info['ExchangeID'],
     )
     self.ReqOrderAction(req, self.inc_request_id())