def __init__(self): self.Session = '' self.q = Quote() self.t = Trade() self.req = 0 self.ordered = False self.needAuth = False self.RelogEnable = True
def __init__(self): super().__init__() self._req = 0 '''防止重连时启用太多查询线程''' self.qryStart = False self.__dic_orderid_sysid = {} self.__posi = [] self.t = Trade()
def __init__(self): self.Session = '' self.q = Quote() self.t = Trade() self.req = 0 self.ordered = False self.needAuth = False self.RelogEnable = False self.frontAddr = '' self.broker = '' self.investor = '' self.pwd = ''
def __init__(self): """API对象的初始化函数""" self.t = Trade() # 请求编号,由api负责管理 self.__reqid = 0 # 报单编号,由api负责管理 self.__orderref = 0 # 以下变量用于实现连接和重连后的自动登陆 self.__userid = '099829' self.__password = '******' self.__brokerid = '9999'
def __init__(self, eventEngine): """API对象的初始化函数""" # 事件引擎,所有数据都推送到其中,再由事件引擎进行分发 self.__eventEngine = eventEngine self.t = Trade() # 请求编号,由api负责管理 self.__reqid = 0 # 报单编号,由api负责管理 self.__orderref = 0 # 以下变量用于实现连接和重连后的自动登陆 self.__userid = '' self.__password = '' self.__brokerid = ''
def __init__(self, eventEngine): """API对象的初始化函数""" # 事件引擎,所有数据都推送到其中,再由事件引擎进行分发 self.__eventEngine = eventEngine self.t = Trade() # 请求编号,由api负责管理 self.__reqid = 0 # 报单编号,由api负责管理 self.__orderref = random.randrange(start=1000, stop=9000, step=random.randint(10, 100)) self.SessionID = None self.FrontID = None # 以下变量用于实现连接和重连后的自动登陆 self.__userid = cf.userid self.__password = cf.password self.__brokerid = cf.brokerid api = self.t.CreateApi() spi = self.t.CreateSpi() self.t.RegisterSpi(spi) self.t.OnFrontConnected = self.onFrontConnected # 交易服务器登陆相应 self.t.OnRspUserLogin = self.onRspUserLogin # 用户登陆 self.t.OnErrRtnOrderInsert = self.onErrRtnOrderInsert self.t.OnRspUserLogout = self.OnRspUserLogout self.t.OnRtnInstrumentStatus = self.OnRtnInstrumentStatus self.t.OnFrontDisconnected = self.onFrontDisconnected self.t.OnRspSettlementInfoConfirm = self.onRspSettlementInfoConfirm # 结算单确认 self.t.OnRspQryInstrument = self.onRspQryInstrument # 查询全部交易合约 self.t.OnRspQryDepthMarketData = self.onRspQryDepthMarketData # tick截面数据 self.t.OnRspQryInvestorPosition = self.onRspQryInvestorPosition #查询持仓 self.t.OnRspQryTradingAccount = self.onRspQryTradingAccount #查询账户 self.t.OnRtnOrder = self.onRtnOrder #报单 self.t.OnRtnTrade = self.onRtnTrade #成交 self.t.OnRspQryInstrumentMarginRate = self.OnRspQryInstrumentMarginRate #获取保证金率 #——————错误事件 self.t.OnRspOrderInsert = self.onRspOrderInsert self.t.OnRspOrderAction = self.onRspOrderAction self.t.OnRspError = self.onRspError self.t.RegCB() self.login_status = False #登录状态
def __init__(self, args): print(dt.datetime.today(), '---- __init__ ----') # self.rootdir = os.path.abspath(os.path.join(os.getcwd(), os.pardir)) self.rootdir = os.getcwd() # parse command line input args self.ProductClass2 = list() if args.product is None else [ x.upper() for x in args.product ] self.ExchangeID2 = list() if args.exchange is None else [ x.upper() for x in args.exchange ] self.ProductID2 = list() if args.underlying is None else [ x.upper() for x in args.underlying ] account = 'real_eb1' if args.account is None else args.account[0] self.mongodb = 'mongodb2' if args.mongodb is None else args.mongodb[0] # print(self.ProductClass2) # print(self.ExchangeID2) # print(self.ProductID2) # print(account) # print(mongodb) # ctp connection, current path is '...\PyCtp' config = SafeConfigParser() ctp_path = os.path.join(os.path.abspath('..'), 'PyShare', 'config', 'ctp_connection.ini') config.read(ctp_path) self.BrokerID = config.get(account, 'BrokerID') self.UserID = config.get(account, 'UserID') self.Password = config.get(account, 'Password') self.q_ip = config.get(account, 'q_ip') self.t_ip = config.get(account, 't_ip') self.Session = '' self.q = Quote() self.t = Trade() self.contract = list() self.contractdf = pd.DataFrame() self.TradingDay = '' # create connection to mongodb, make sure it is primary connection mongo_path = os.path.join(os.path.abspath('..'), 'PyShare', 'config', 'mongodb_connection.ini') self.mdb = Mongo.MongoDB(mongo_path)
def __init__(self): """初始化 运行的目录下需要创建log目录""" """交易前置""" self.front_trade = '' # 行情前置 self.front_quote = '' self.investor = '' self.pwd = '' self.broker = '' self.TradingDay = '' # self.log = open('orders.csv', 'w') # self.log.write('') # 清空内容 self.stra_instances = [] self.Session = '' self.q = Quote() self.t = Trade() self.req = 0 self.ordered = False self.needAuth = False
class TdApi: """ Demo中的交易API封装 主动函数包括: login 登陆 getInstrument 查询合约信息 getAccount 查询账号资金 getInvestor 查询投资者 getPosition 查询持仓 sendOrder 发单 cancelOrder 撤单 """ #---------------------------------------------------------------------- def __init__(self, eventEngine): """API对象的初始化函数""" # 事件引擎,所有数据都推送到其中,再由事件引擎进行分发 self.__eventEngine = eventEngine self.t = Trade() # 请求编号,由api负责管理 self.__reqid = 0 # 报单编号,由api负责管理 self.__orderref = 0 # 以下变量用于实现连接和重连后的自动登陆 self.__userid = '' self.__password = '' self.__brokerid = '' def login(self): api = self.t.CreateApi() spi = self.t.CreateSpi() self.t.RegisterSpi(spi) self.t.OnFrontConnected = self.onFrontConnected # 交易服务器登陆相应 self.t.RegCB() self.t.RegisterFront('tcp://180.168.146.187:10000') self.t.Init() def onFrontConnected(self): """服务器连接""" event = Event(type_=EVENT_LOG) event.dict_['log'] = ('交易服务器连接成功') self.__eventEngine.put(event)
class Test: def __init__(self): self.Session = '' self.q = Quote() self.t = Trade() self.req = 0 self.ordered = False self.needAuth = False self.RelogEnable = True def q_OnFrontConnected(self): print('connected') self.q.ReqUserLogin(BrokerID=self.broker, UserID=self.investor, Password=self.pwd) def q_OnRspUserLogin(self, rsp, info, req, last): print(info) #insts = create_string_buffer(b'cu', 5) self.q.SubscribeMarketData('rb1810') def q_OnTick(self, tick): f = CThostFtdcMarketDataField() f = tick #print(tick) if not self.ordered: _thread.start_new_thread(self.Order, (f, )) self.ordered = True def Order(self, f): print("报单") self.req += 1 self.t.ReqOrderInsert( BrokerID=self.broker, InvestorID=self.investor, InstrumentID=f.getInstrumentID(), OrderRef='{0:>12}'.format(self.req), UserID=self.investor, OrderPriceType=OrderPriceTypeType.LimitPrice, Direction=DirectionType.Buy, CombOffsetFlag=OffsetFlagType.Open.__char__(), CombHedgeFlag=HedgeFlagType.Speculation.__char__(), LimitPrice=f.getLastPrice() - 50, VolumeTotalOriginal=1, TimeCondition=TimeConditionType.GFD, #GTDDate='' VolumeCondition=VolumeConditionType.AV, MinVolume=1, ContingentCondition=ContingentConditionType.Immediately, StopPrice=0, ForceCloseReason=ForceCloseReasonType.NotForceClose, IsAutoSuspend=0, IsSwapOrder=0, UserForceClose=0) def OnFrontConnected(self): if not self.RelogEnable: return print('connected') if self.needAuth: self.t.ReqAuthenticate(self.broker, self.investor, '@haifeng', '8MTL59FK1QGLKQW2') else: self.t.ReqUserLogin(BrokerID=self.broker, UserID=self.investor, Password=self.pwd, UserProductInfo='@haifeng') def OnRspAuthenticate(self, pRspAuthenticateField=CThostFtdcRspAuthenticateField, pRspInfo=CThostFtdcRspInfoField, nRequestID=int, bIsLast=bool): print('auth:{0}:{1}'.format(pRspInfo.getErrorID(), pRspInfo.getErrorMsg())) self.t.ReqUserLogin(BrokerID=self.broker, UserID=self.investor, Password=self.pwd, UserProductInfo='@haifeng') def OnRspUserLogin(self, rsp, info, req, last): i = CThostFtdcRspInfoField() i = info print(i.getErrorMsg()) if i.getErrorID() == 0: self.Session = rsp.getSessionID() self.t.ReqSettlementInfoConfirm(BrokerID=self.broker, InvestorID=self.investor) else: self.RelogEnable = False def OnRspSettlementInfoConfirm( self, pSettlementInfoConfirm=CThostFtdcSettlementInfoConfirmField, pRspInfo=CThostFtdcRspInfoField, nRequestID=int, bIsLast=bool): #print(pSettlementInfoConfirm) _thread.start_new_thread(self.StartQuote, ()) def StartQuote(self): api = self.q.CreateApi() spi = self.q.CreateSpi() self.q.RegisterSpi(spi) self.q.OnFrontConnected = self.q_OnFrontConnected self.q.OnRspUserLogin = self.q_OnRspUserLogin self.q.OnRtnDepthMarketData = self.q_OnTick self.q.RegCB() self.q.RegisterFront(self.frontAddr.split(',')[1]) self.q.Init() #self.q.Join() def Qry(self): sleep(1.1) self.t.ReqQryInstrument() while True: sleep(1.1) self.t.ReqQryTradingAccount(self.broker, self.investor) sleep(1.1) self.t.ReqQryInvestorPosition(self.broker, self.investor) return def OnRtnInstrumentStatus(self, pInstrumentStatus=CThostFtdcInstrumentStatusField ): pass def OnRspOrderInsert(self, pInputOrder=CThostFtdcInputOrderField, pRspInfo=CThostFtdcRspInfoField, nRequestID=int, bIsLast=bool): print(pRspInfo) print(pInputOrder) print(pRspInfo.getErrorMsg()) def OnRtnOrder(self, pOrder=CThostFtdcOrderField): #print(pOrder) if pOrder.getSessionID() == self.Session and pOrder.getOrderStatus( ) == OrderStatusType.NoTradeQueueing: print("撤单") self.t.ReqOrderAction(self.broker, self.investor, InstrumentID=pOrder.getInstrumentID(), OrderRef=pOrder.getOrderRef(), FrontID=pOrder.getFrontID(), SessionID=pOrder.getSessionID(), ActionFlag=ActionFlagType.Delete) def Run(self): #CreateApi时会用到log目录,需要在程序目录下创建**而非dll下** api = self.t.CreateApi() spi = self.t.CreateSpi() self.t.RegisterSpi(spi) self.t.OnFrontConnected = self.OnFrontConnected self.t.OnRspUserLogin = self.OnRspUserLogin self.t.OnRspSettlementInfoConfirm = self.OnRspSettlementInfoConfirm self.t.OnRspAuthenticate = self.OnRspAuthenticate self.t.OnRtnInstrumentStatus = self.OnRtnInstrumentStatus self.t.OnRspOrderInsert = self.OnRspOrderInsert self.t.OnRtnOrder = self.OnRtnOrder #_thread.start_new_thread(self.Qry, ()) self.t.RegCB() self.frontAddr = 'tcp://180.168.146.187:10000,tcp://180.168.146.187:10010' self.broker = '9999' self.investor = '008105' self.pwd = '1' self.t.RegisterFront(self.frontAddr.split(',')[0]) self.t.SubscribePrivateTopic(nResumeType=2) #quick self.t.SubscribePrivateTopic(nResumeType=2) self.t.Init() self.t.Join()
class TdApi: """ Demo中的交易API封装 主动函数包括: login 登陆 getInstrument 查询合约信息 getAccount 查询账号资金 getInvestor 查询投资者 getPosition 查询持仓 sendOrder 发单 cancelOrder 撤单 """ #---------------------------------------------------------------------- def __init__(self): """API对象的初始化函数""" self.t = Trade() # 请求编号,由api负责管理 self.__reqid = 0 # 报单编号,由api负责管理 self.__orderref = 0 # 以下变量用于实现连接和重连后的自动登陆 self.__userid = '099829' self.__password = '******' self.__brokerid = '9999' def login(self): api = self.t.CreateApi() spi = self.t.CreateSpi() self.t.RegisterSpi(spi) self.t.OnFrontConnected = self.onFrontConnected # 交易服务器登陆相应 self.t.OnRspUserLogin = self.onRspUserLogin # 用户登陆 self.t.OnRtnInstrumentStatus = self.OnRtnInstrumentStatus #这个函数在合约交易状态发生改变时会被调用(会通知当前交易所状态变化开市,休市,闭市时) self.t.RegCB() self.t.RegisterFront('tcp://180.168.146.187:10000') #注册前置地址 self.t.Init() #初始化接口线程 def onFrontConnected(self): """交易服务器连接""" logging.info("交易服务器连接成功") #也可以直接print("交易服务器连接成功") self.t.ReqUserLogin(BrokerID=self.__brokerid, UserID=self.__userid, Password=self.__password) #返回onRspUserLogin和OnRtnInstrumentStatus两个回报, def OnRtnInstrumentStatus(self, data): #合约的情况,pass不处理信息 pass def onRspUserLogin(self, data, error, n, last): """登陆回报""" if error.__dict__['ErrorID'] == 0: self.Investor = data.__dict__['UserID'] self.BrokerID = data.__dict__['BrokerID'] log = data.__dict__['UserID'] + '交易服务器登陆成功' #self.t.ReqSettlementInfoConfirm(self.BrokerID, self.Investor) # 对账单确认,现在时注销状态 else: log = '登陆回报,错误代码:' + str(error.__dict__['ErrorID']) + ', 错误信息:' + str(error.__dict__['ErrorMsg']) logging.info(log)
class Test: def __init__(self): """初始化 运行的目录下需要创建log目录""" """交易前置""" self.front_trade = '' # 行情前置 self.front_quote = '' self.investor = '' self.pwd = '' self.broker = '' self.TradingDay = '' # self.log = open('orders.csv', 'w') # self.log.write('') # 清空内容 self.stra_instances = [] self.Session = '' self.q = Quote() self.t = Trade() self.req = 0 self.ordered = False self.needAuth = False def q_OnFrontConnected(self): print('connected') self.q.ReqUserLogin(BrokerID=self.broker, UserID=self.investor, Password=self.pwd) def q_OnRspUserLogin(self, rsp, info, req, last): print(info) self.q.SubscribeMarketData('rb1805') def q_OnRspSubMarketData( self, pSpecificInstrument=CThostFtdcSpecificInstrumentField, pRspInfo=CThostFtdcRspInfoField, nRequestID=int, bIsLast=bool): pass def q_OnTick(self, tick): f = CThostFtdcMarketDataField() f = tick if not self.ordered: print(tick) _thread.start_new_thread(self.Order, (f, )) self.ordered = True def Order(self, f): print("报单") self.req += 1 self.t.ReqOrderInsert( BrokerID=self.broker, InvestorID=self.investor, InstrumentID=f.getInstrumentID(), OrderRef='{0:>12}'.format(self.req), UserID=self.investor, OrderPriceType=OrderPriceTypeType.LimitPrice, Direction=DirectionType.Buy, CombOffsetFlag=OffsetFlagType.Open.__char__(), CombHedgeFlag=HedgeFlagType.Speculation.__char__(), LimitPrice=f.getLastPrice() - 50, VolumeTotalOriginal=1, TimeCondition=TimeConditionType.GFD, # GTDDate='' VolumeCondition=VolumeConditionType.AV, MinVolume=1, ContingentCondition=ContingentConditionType.Immediately, StopPrice=0, ForceCloseReason=ForceCloseReasonType.NotForceClose, IsAutoSuspend=0, IsSwapOrder=0, UserForceClose=0) def OnFrontConnected(self): print('connected') if self.needAuth: self.t.ReqAuthenticate(self.broker, self.investor, '@haifeng', '8MTL59FK1QGLKQW2') else: self.t.ReqUserLogin(BrokerID=self.broker, UserID=self.investor, Password=self.pwd, UserProductInfo='@haifeng') def OnRspAuthenticate(self, pRspAuthenticateField=CThostFtdcRspAuthenticateField, pRspInfo=CThostFtdcRspInfoField, nRequestID=int, bIsLast=bool): print('auth:{0}:{1}'.format(pRspInfo.getErrorID(), pRspInfo.getErrorMsg())) self.t.ReqUserLogin(BrokerID=self.broker, UserID=self.investor, Password=self.pwd, UserProductInfo='@haifeng') def OnRspUserLogin(self, rsp, info, req, last): print(info) i = CThostFtdcRspInfoField() i = info if i.getErrorID() == 0: self.Session = rsp.getSessionID() self.t.ReqSettlementInfoConfirm(BrokerID=self.broker, InvestorID=self.investor) def OnRspSettlementInfoConfirm( self, pSettlementInfoConfirm=CThostFtdcSettlementInfoConfirmField, pRspInfo=CThostFtdcRspInfoField, nRequestID=int, bIsLast=bool): _thread.start_new_thread(self.StartQuote, ()) _thread.start_new_thread(self.Qry, ()) def StartQuote(self): print('start quote') self.q.CreateApi() spi = self.q.CreateSpi() self.q.RegisterSpi(spi) self.q.OnFrontConnected = self.q_OnFrontConnected self.q.OnRspUserLogin = self.q_OnRspUserLogin self.q.OnRtnDepthMarketData = self.q_OnTick self.q.OnRspSubMarketData = self.q_OnRspSubMarketData self.q.RegCB() self.q.RegisterFront(self.front_quote) self.q.Init() # self.q.Join() def Qry(self): sleep(1.1) self.t.ReqQryInstrument() while True: sleep(1.1) self.t.ReqQryTradingAccount(self.broker, self.investor) sleep(1.1) self.t.ReqQryInvestorPosition(self.broker, self.investor) return def OnRtnInstrumentStatus(self, pInstrumentStatus=CThostFtdcInstrumentStatusField ): pass def OnRspOrderInsert(self, pInputOrder=CThostFtdcInputOrderField, pRspInfo=CThostFtdcRspInfoField, nRequestID=int, bIsLast=bool): print(pRspInfo) print(pInputOrder) print(pRspInfo.getErrorMsg()) def OnRtnOrder(self, pOrder=CThostFtdcOrderField): # print(pOrder) if pOrder.getSessionID() == self.Session and pOrder.getOrderStatus( ) == OrderStatusType.NoTradeQueueing: print("撤单") self.t.ReqOrderAction(self.broker, self.investor, InstrumentID=pOrder.getInstrumentID(), OrderRef=pOrder.getOrderRef(), FrontID=pOrder.getFrontID(), SessionID=pOrder.getSessionID(), ActionFlag=ActionFlagType.Delete) def OnRspInstrument(self, instrument, rspinfo, nreq, last): pass def OnRspPosition(self, pInvestorPosition=CThostFtdcInvestorPositionField, pRspInfo=CThostFtdcRspInfoField, nRequestID=int, bIsLast=bool): pass def OnRspAccount(self, pTradingAccount=CThostFtdcTradingAccountField, pRspInfo=CThostFtdcRspInfoField, nRequestID=int, bIsLast=bool): pass def CTPRun(self, front_trade='tcp://180.168.146.187:10000', front_quote='tcp://180.168.146.187:10010', broker='9999', investor='008109', pwd='1'): """""" self.front_trade = front_trade self.front_quote = front_quote self.broker = broker self.investor = investor self.pwd = pwd self.t.CreateApi() spi = self.t.CreateSpi() self.t.SubscribePrivateTopic(2) self.t.SubscribePublicTopic(2) self.t.RegisterSpi(spi) self.t.OnFrontConnected = self.OnFrontConnected self.t.OnRspUserLogin = self.OnRspUserLogin self.t.OnRspSettlementInfoConfirm = self.OnRspSettlementInfoConfirm self.t.OnRspQryInstrument = self.OnRspInstrument self.t.OnRtnInstrumentStatus = self.OnRtnInstrumentStatus self.t.OnRtnOrder = self.OnRtnOrder self.t.OnRspQryInvestorPosition = self.OnRspPosition self.t.OnRspQryTradingAccount = self.OnRspAccount # self.t.OnRtnTrade = self.OnRtnTrade # self.t.OnRtnCancel = self.OnRtnCancel # self.t.OnRtnErrOrder = self.OnRtnErrOrder self.t.RegCB() self.t.RegisterFront(self.front_trade) self.t.Init()
class CtpTrade(TradeAdapter): """""" def __init__(self): super().__init__() self._req = 0 '''防止重连时启用太多查询线程''' self.qryStart = False self.__dic_orderid_sysid = {} self.__posi = [] self.t = Trade() def __qry(self): """查询帐号相关信息""" self.qryStart = True # restart 模式, 待rtnorder 处理完毕后再进行查询,否则会造成position混乱 ord_cnt = 0 while True: time.sleep(0.5) if len(self.DicOrderField) == ord_cnt: break ord_cnt = len(self.DicOrderField) self.t.ReqQryInstrument() time.sleep(1.1) while not self.Account or self.IsLogin: """查询持仓与权益""" time.sleep(1.1) self.t.ReqQryInvestorPosition(self.BrokerID, self.Investor) time.sleep(1.1) self.t.ReqQryTradingAccount(self.BrokerID, self.Investor) def __OnFrontConnected(self): self.OnFrontConnected() def __OnFrontDisconnected(self, nReason): self.IsLogin = False self.OnFrontDisConnected(nReason) def __OnRspUserLogin(self, pRspUserLogin=CThostFtdcRspUserLoginField(), pRspInfo=CThostFtdcRspInfoField, nRequestID=int, bIsLast=bool): self.Investor = pRspUserLogin.getUserID() self.BrokerID = pRspUserLogin.getBrokerID() self.SessionID = pRspUserLogin.getSessionID() self.TradingDay = pRspUserLogin.getTradingDay() if pRspInfo.getErrorID() != 0: info = InfoField() info.ErrorID = pRspInfo.getErrorID() info.ErrorMsg = pRspInfo.getErrorMsg() self.OnRspUserLogin(info) else: self.t.ReqSettlementInfoConfirm(self.BrokerID, self.Investor) if not self.qryStart: time.sleep(0.5) """查询持仓与权益""" _thread.start_new_thread(self.__qry, ()) # 开启查询 def __OnRspQryInstrument(self, pInstrument=CThostFtdcInstrumentField, pRspInfo=CThostFtdcRspInfoField, nRequestID=int, bIsLast=bool): """""" inst = InstrumentField() inst.InstrumentID = pInstrument.getInstrumentID() inst.ProductID = pInstrument.getProductID() inst.ExchangeID = pInstrument.getExchangeID() inst.VolumeMultiple = pInstrument.getVolumeMultiple() inst.PriceTick = pInstrument.getPriceTick() inst.MaxOrderVolume = pInstrument.getMaxLimitOrderVolume() self.DicInstrument[inst.InstrumentID] = inst def __OnRspQryAccount(self, pTradingAccount=CThostFtdcTradingAccountField, pRspInfo=CThostFtdcRspInfoField, nRequestID=int, bIsLast=bool): """""" if not self.Account: self.Account = TradingAccount() self.Account.Available = pTradingAccount.getAvailable() self.Account.CloseProfit = pTradingAccount.getCloseProfit() self.Account.Commission = pTradingAccount.getCommission() self.Account.CurrMargin = pTradingAccount.getCurrMargin() self.Account.FrozenCash = pTradingAccount.getFrozenCash() self.Account.PositionProfit = pTradingAccount.getPositionProfit() self.Account.PreBalance = pTradingAccount.getPreBalance( ) + pTradingAccount.getDeposit() + pTradingAccount.getWithdraw() self.Account.Fund = self.Account.PreBalance + pTradingAccount.getCloseProfit( ) + pTradingAccount.getPositionProfit( ) - pTradingAccount.getCommission() self.Account.Risk = self.Account.CurrMargin / self.Account.Fund if not self.IsLogin: self.IsLogin = True info = InfoField() info.ErrorID = 0 info.ErrorMsg = '正确' self.OnRspUserLogin(info) def __OnRspQryPosition(self, pInvestorPosition=CThostFtdcInvestorPositionField, pRspInfo=CThostFtdcRspInfoField, nRequestID=int, bIsLast=bool): """""" if pInvestorPosition.getInstrumentID() != '': # 偶尔出现NULL的数据导致数据转换错误 self.__posi.append( pInvestorPosition) # Struct(**f.__dict__)) #dict -> object if bIsLast: # 先排序再group才有效 self.__posi = sorted( self.__posi, key=lambda c: '{0}_{1}'.format( c.getInstrumentID(), DirectType.Buy if c.getPosiDirection( ) == PosiDirectionType.Long else DirectType.Sell)) # direction需从posidiction转换为dictiontype for key, group in itertools.groupby( self.__posi, lambda c: '{0}_{1}'.format( c.getInstrumentID(), DirectType.Buy if c.getPosiDirection() == PosiDirectionType.Long else DirectType.Sell)): pf = self.DicPositionField.get(key) if not pf: pf = PositionField() self.DicPositionField[key] = pf pf.Position = 0 pf.TdPosition = 0 pf.YdPosition = 0 pf.CloseProfit = 0 pf.PositionProfit = 0 pf.Commission = 0 pf.Margin = 0 pf.Price = 0 cost = 0.0 for g in group: if not pf.InstrumentID: pf.InstrumentID = g.getInstrumentID() pf.Direction = DirectType.Buy if g.getPosiDirection( ) == PosiDirectionType.Long else DirectType.Sell pf.Position += g.getPosition() pf.TdPosition += g.getTodayPosition() pf.YdPosition = pf.Position - pf.TdPosition pf.CloseProfit += g.getCloseProfit() pf.PositionProfit += g.getPositionProfit() pf.Commission += g.getCommission() pf.Margin += g.getUseMargin() cost += g.OpenCost # pf.Position <= 0 ? 0 : (g.Sum(n => n.PositionCost) / DicInstrumentField[pf.InstrumentID].VolumeMultiple / pf.Position); vm = self.DicInstrument[pf.InstrumentID].VolumeMultiple pf.Price = 0 if pf.Position <= 0 else cost / vm / pf.Position self.__posi.clear() def __OnRtnOrder(self, pOrder=CThostFtdcOrderField): """""" id = '{0}|{1}|{2}'.format(pOrder.getSessionID(), pOrder.getFrontID(), pOrder.getOrderRef()) # of = OrderField() of = self.DicOrderField.get(id) if not of: of = OrderField() l = int(pOrder.getOrderRef()) of.Custom = l % 1000000 of.InstrumentID = pOrder.getInstrumentID() of.InsertTime = pOrder.getInsertTime() of.Direction = DirectType.Buy if DirectionType(pOrder.getDirection( )) == DirectionType.Buy else DirectType.Sell ot = OffsetFlagType(ord(pOrder.getCombOffsetFlag()[0])) of.Offset = OffsetType.Open if ot == OffsetFlagType.Open else ( OffsetType.CloseToday if ot == OffsetFlagType.CloseToday else OffsetType.Close) of.Status = OrderStatus.Normal of.StatusMsg = pOrder.getStatusMsg() of.IsLocal = pOrder.getSessionID() == self.SessionID of.LimitPrice = pOrder.getLimitPrice() of.OrderID = id of.Volume = pOrder.getVolumeTotalOriginal() of.VolumeLeft = of.Volume self.DicOrderField[id] = of self.OnRtnOrder(of) # _thread.start_new_thread(self.OnRtnOrder, (of,)) # call client OnRtnOrder event elif pOrder.getOrderStatus() == OrderStatusType.Canceled: of.Status = OrderStatus.Canceled of.StatusMsg = pOrder.getStatusMsg() if of.StatusMsg.find('被拒绝') >= 0: info = InfoField() info.ErrorID = -1 info.ErrorMsg = of.StatusMsg self.OnRtnErrOrder(of, info) else: self.OnRtnCancel(of) else: if pOrder.getOrderSysID(): of.SysID = pOrder.getOrderSysID() self.__dic_orderid_sysid[pOrder.getOrderSysID( )] = id # 记录sysid与orderid关联,方便Trade时查找处理 # _thread.start_new_thread(self.OnRtnOrder, (of,)) def __OnRtnTrade(self, f): """""" tf = TradeField() tf.Direction = DirectType.Buy if f.getDirection( ) == DirectionType.Buy else DirectType.Sell tf.ExchangeID = f.getExchangeID() tf.InstrumentID = f.getInstrumentID() tf.Offset = OffsetType.Open if f.getOffsetFlag( ) == OffsetFlagType.Open else OffsetType.Close if f.getOffsetFlag( ) == OffsetFlagType.Close else OffsetType.CloseToday tf.Price = f.getPrice() tf.SysID = f.getOrderSysID() tf.TradeID = f.getTradeID() tf.TradeTime = f.getTradeTime() tf.TradingDay = f.getTradingDay() tf.Volume = f.getVolume() self.DicTradeField[tf.TradeID] = tf id = self.__dic_orderid_sysid[tf.SysID] of = self.DicOrderField[id] tf.OrderID = id # tradeid 与 orderid 关联 of.TradeTime = tf.TradeTime # of.AvgPrice = (of.AvgPrice * (of.Volume - of.VolumeLeft) + pTrade.Price * pTrade.Volume) / (of.Volume - of.VolumeLeft + pTrade.Volume); of.AvgPrice = (of.AvgPrice * (of.Volume - of.VolumeLeft) + tf.Price * tf.Volume) / ( of.Volume - of.VolumeLeft + tf.Volume) of.TradeVolume = tf.Volume of.VolumeLeft -= tf.Volume if of.VolumeLeft == 0: of.Status = OrderStatus.Filled of.StatusMsg = '全部成交' else: of.Status = OrderStatus.Partial of.StatusMsg = '部分成交' # 更新持仓 ***** if tf.Offset == OffsetType.Open: key = '{0}_{1}'.format(tf.InstrumentID, tf.Direction) pf = self.DicPositionField.get(key) if not pf: pf = PositionField() self.DicPositionField[key] = pf pf.InstrumentID = tf.InstrumentID pf.Direction = tf.Direction pf.Price = (pf.Price * pf.Position + tf.Price * tf.Volume) / (pf.Position + tf.Volume) pf.TdPosition += tf.Volume pf.Position += tf.Volume else: key = '{0}_{1}'.format( tf.InstrumentID, DirectType.Sell if tf.Direction == DirectType.Buy else DirectType.Buy) pf = self.DicPositionField.get(key) if pf: # 有可能出现无持仓的情况 if tf.Offset == OffsetType.CloseToday: pf.TdPosition -= tf.Volume else: tdclose = min(pf.TdPosition, tf.Volume) if pf.TdPosition > 0: pf.TdPosition -= tdclose pf.YdPosition -= max(0, tf.Volume - tdclose) pf.Position -= tf.Volume _thread.start_new_thread(self.__onRtn, (of, tf)) # _thread.start_new_thread(self.OnRtnOrder, (of,)) # _thread.start_new_thread(self.OnRtnTrade, (tf,)) def __onRtn(self, of, tf): self.OnRtnOrder(of) self.OnRtnTrade(tf) def __OnRspOrder(self, pInputOrder=CThostFtdcInputOrderField, pRspInfo=CThostFtdcRspInfoField, nRequestID=int, bIsLast=bool): """""" info = InfoField() info.ErrorID = pRspInfo.getErrorID() info.ErrorMsg = pRspInfo.getErrorMsg() id = '{0}|{1}|{2}'.format(self.SessionID, '0', pInputOrder.getOrderRef()) of = self.DicOrderField.get(id) if not of: of = OrderField() l = int(pInputOrder.getOrderRef()) of.Custom = l % 1000000 of.InstrumentID = pInputOrder.getInstrumentID() of.InsertTime = time.strftime('%Y%M%d %H:%M:%S', time.localtime()) # 对direction需特别处理(具体见ctp_struct) of.Direction = DirectType.Buy if DirectionType( pInputOrder.getDirection( )) == DirectionType.Buy else DirectType.Sell ot = OffsetFlagType(ord(pInputOrder.getCombOffsetFlag()[0])) of.Offset = OffsetType.Open if ot == OffsetFlagType.Open else ( OffsetType.CloseToday if ot == OffsetFlagType.CloseToday else OffsetType.Close) # of.Status = OrderStatus.Normal # of.StatusMsg = f.getStatusMsg() of.IsLocal = True of.LimitPrice = pInputOrder.getLimitPrice() of.OrderID = id of.Volume = pInputOrder.getVolumeTotalOriginal() of.VolumeLeft = of.Volume self.DicOrderField[id] = of of.Status = OrderStatus.Error of.StatusMsg = '{0}:{1}'.format(info.ErrorID, info.ErrorMsg) _thread.start_new_thread(self.OnRtnErrOrder, (of, info)) def __OnErrOrder(self, pInputOrder=CThostFtdcInputOrderField, pRspInfo=CThostFtdcRspInfoField): """""" id = '{0}|{1}|{2}'.format(self.SessionID, '0', pInputOrder.getOrderRef()) of = self.DicOrderField.get(id) info = InfoField() info.ErrorID = pRspInfo.getErrorID() info.ErrorMsg = pRspInfo.getErrorMsg() if of and of.IsLocal: of.Status = OrderStatus.Error of.StatusMsg = '{0}:{1}'.format(pRspInfo.getErrorID(), pRspInfo.getErrorMsg()) _thread.start_new_thread(self.OnRtnErrOrder, (of, info)) def __OnRspOrderAction(self, pInputOrderAction=CThostFtdcInputOrderActionField, pRspInfo=CThostFtdcRspInfoField, nRequestID=int, bIsLast=bool): id = "{0}|{1}|{2}".format(pInputOrderAction.getSessionID(), pInputOrderAction.getFrontID(), pInputOrderAction.getOrderRef()) if self.IsLogin and id in self.DicOrderField: info = InfoField() info.ErrorID = pRspInfo.ErrorID info.ErrorMsg = pRspInfo.ErrorMsg self.OnErrCancel(self.DicOrderField[id], info) def __OnRtnInstrumentStatus( self, pInstrumentStatus=CThostFtdcInstrumentStatusField): self.DicInstrumentStatus[pInstrumentStatus.getInstrumentID( )] = pInstrumentStatus.getInstrumentStatus() _thread.start_new_thread(self.OnRtnInstrumentStatus, (pInstrumentStatus.getInstrumentID(), pInstrumentStatus.getInstrumentStatus())) def __OnRspSettlementInfoConfirm( self, pSettlementInfoConfirm=CThostFtdcSettlementInfoConfirmField, pRspInfo=CThostFtdcRspInfoField, nRequestID=int, bIsLast=bool): pass def ReqConnect(self, pAddress=''): self.t.CreateApi() spi = self.t.CreateSpi() self.t.SubscribePrivateTopic(0) # restart 同步处理order trade self.t.SubscribePublicTopic(0) self.t.RegisterSpi(spi) self.t.OnFrontConnected = self.__OnFrontConnected self.t.OnRspUserLogin = self.__OnRspUserLogin self.t.OnFrontDisconnected = self.__OnFrontDisconnected self.t.OnRspSettlementInfoConfirm = self.__OnRspSettlementInfoConfirm self.t.OnRtnOrder = self.__OnRtnOrder self.t.OnRtnTrade = self.__OnRtnTrade self.t.OnRspOrderInsert = self.__OnRspOrder self.t.OnErrRtnOrderInsert = self.__OnErrOrder self.t.OnRspOrderAction = self.__OnRspOrderAction self.t.OnRtnInstrumentStatus = self.__OnRtnInstrumentStatus self.t.OnRspQryInstrument = self.__OnRspQryInstrument self.t.OnRspQryTradingAccount = self.__OnRspQryAccount self.t.OnRspQryInvestorPosition = self.__OnRspQryPosition self.t.RegCB() self.t.RegisterFront(pAddress) self.t.Init() # self.t.Join() def ReqUserLogin(self, user, pwd, broker): self.t.ReqUserLogin(BrokerID=broker, UserID=user, Password=pwd) def ReqOrderInsert(self, pInstrument='', pDirection=DirectType, pOffset=OffsetType, pPrice=0.0, pVolume=1, pType=OrderType.Limit, pCustom=0): """""" OrderPriceType = OrderPriceTypeType.AnyPrice TimeCondition = TimeConditionType.IOC LimitPrice = 0.0 VolumeCondition = VolumeConditionType.AV for case in switch(pType): if case(OrderType.Market): # 市价 OrderPriceType = OrderPriceTypeType.AnyPrice TimeCondition = TimeConditionType.IOC LimitPrice = 0.0 VolumeCondition = VolumeConditionType.AV break if case(OrderType.Limit): # 限价 OrderPriceType = OrderPriceTypeType.LimitPrice TimeCondition = TimeConditionType.GFD LimitPrice = pPrice VolumeCondition = VolumeConditionType.AV break if case(OrderType.FAK): # FAK OrderPriceType = OrderPriceTypeType.LimitPrice TimeCondition = TimeConditionType.IOC LimitPrice = pPrice VolumeCondition = VolumeConditionType.AV break if case(OrderType.FOK): # FOK OrderPriceType = OrderPriceTypeType.LimitPrice TimeCondition = TimeConditionType.IOC LimitPrice = pPrice VolumeCondition = VolumeConditionType.CV # 全部数量 break self._req += 1 self.t.ReqOrderInsert( BrokerID=self.BrokerID, InvestorID=self.Investor, InstrumentID=pInstrument, OrderRef="%06d%06d" % (self._req, pCustom % 1000000), UserID=self.Investor, # 此处ctp_enum与at_struct名称冲突 Direction=DirectionType.Buy if pDirection == DirectType.Buy else DirectionType.Sell, CombOffsetFlag=chr( OffsetFlagType.Open if pOffset == OffsetType.Open else ( OffsetFlagType.CloseToday if pOffset == OffsetType.CloseToday else OffsetFlagType.Close)), CombHedgeFlag=HedgeFlagType.Speculation.__char__(), IsAutoSuspend=0, ForceCloseReason=ForceCloseReasonType.NotForceClose, IsSwapOrder=0, ContingentCondition=ContingentConditionType.Immediately, VolumeCondition=VolumeCondition, MinVolume=1, VolumeTotalOriginal=pVolume, OrderPriceType=OrderPriceType, TimeCondition=TimeCondition, LimitPrice=LimitPrice, ) def ReqOrderAction(self, OrderID=''): """""" of = self.DicOrderField[OrderID] if not of: return -1 else: pOrderId = of.OrderID return self.t.ReqOrderAction(self.BrokerID, self.Investor, OrderRef=pOrderId.split('|')[2], FrontID=int(pOrderId.split('|')[1]), SessionID=int(pOrderId.split('|')[0]), InstrumentID=of.InstrumentID, ActionFlag=ActionFlagType.Delete) def Release(self): self.t.RegisterSpi(None) self.t.Release() def OnFrontConnected(self): """接口连接""" pass def OnFrontDisConnected(self, error=0): """接口断开""" pass def OnRspUserLogin(self, info=InfoField): """登录响应""" pass def OnRtnOrder(self, f=OrderField): """委托返回""" pass def OnRtnTrade(self, f=TradeField): """成交返回""" pass def OnRtnCancel(self, f=OrderField): """撤单响应""" pass def OnErrCancel(self, f=OrderField, info=InfoField): """撤单失败""" pass def OnRtnErrOrder(self, f=OrderField, info=InfoField): """委托错误响应""" print(f) print(info) def OnRtnInstrumentStatus(self, inst, status): pass
def __init__(self): super().__init__() self._req = 0 self.__dic_orderid_sysid = {} self.__posi = [] self.t = Trade()
class TdApi: """ Demo中的交易API封装 主动函数包括: login 登陆 getInstrument 查询合约信息 getAccount 查询账号资金 getInvestor 查询投资者 getPosition 查询持仓 sendOrder 发单 cancelOrder 撤单 """ #---------------------------------------------------------------------- def __init__(self, eventEngine): """API对象的初始化函数""" # 事件引擎,所有数据都推送到其中,再由事件引擎进行分发 self.__eventEngine = eventEngine self.t = Trade() # 请求编号,由api负责管理 self.__reqid = 0 # 报单编号,由api负责管理 self.__orderref = random.randrange(start=1000, stop=9000, step=random.randint(10, 100)) self.SessionID = None self.FrontID = None # 以下变量用于实现连接和重连后的自动登陆 self.__userid = cf.userid self.__password = cf.password self.__brokerid = cf.brokerid api = self.t.CreateApi() spi = self.t.CreateSpi() self.t.RegisterSpi(spi) self.t.OnFrontConnected = self.onFrontConnected # 交易服务器登陆相应 self.t.OnRspUserLogin = self.onRspUserLogin # 用户登陆 self.t.OnErrRtnOrderInsert = self.onErrRtnOrderInsert self.t.OnRspUserLogout = self.OnRspUserLogout self.t.OnRtnInstrumentStatus = self.OnRtnInstrumentStatus self.t.OnFrontDisconnected = self.onFrontDisconnected self.t.OnRspSettlementInfoConfirm = self.onRspSettlementInfoConfirm # 结算单确认 self.t.OnRspQryInstrument = self.onRspQryInstrument # 查询全部交易合约 self.t.OnRspQryDepthMarketData = self.onRspQryDepthMarketData # tick截面数据 self.t.OnRspQryInvestorPosition = self.onRspQryInvestorPosition #查询持仓 self.t.OnRspQryTradingAccount = self.onRspQryTradingAccount #查询账户 self.t.OnRtnOrder = self.onRtnOrder #报单 self.t.OnRtnTrade = self.onRtnTrade #成交 self.t.OnRspQryInstrumentMarginRate = self.OnRspQryInstrumentMarginRate #获取保证金率 #——————错误事件 self.t.OnRspOrderInsert = self.onRspOrderInsert self.t.OnRspOrderAction = self.onRspOrderAction self.t.OnRspError = self.onRspError self.t.RegCB() self.login_status = False #登录状态 def login(self): if self.login_status == False: self.t.RegisterFront('tcp://180.168.146.187:10000') self.t.Init() def logout(self): if self.login_status == True: self.t.ReqUserLogout(self.__brokerid, self.__userid) def release(self): self.t.Release() self.t = None def put_log_event(self, log): # log事件注册 event = Event(type_=EVENT_LOG) event.dict_['log'] = log self.__eventEngine.put(event) def onFrontConnected(self): """服务器连接""" lc.loger.info(threading.current_thread()) self.put_log_event('交易服务器连接成功') time.sleep(3) self.t.ReqUserLogin(BrokerID=self.__brokerid, UserID=self.__userid, Password=self.__password) def OnRtnInstrumentStatus(self, data): pass def onFrontDisconnected(self, n): """服务器断开""" lc.loger.info(threading.current_thread()) self.put_log_event('交易服务器连接断开') self.login_status = False time.sleep(3) def onRspUserLogin(self, data, error, n, last): """登陆回报""" if error.__dict__['ErrorID'] == 0: self.Investor = data.__dict__['UserID'] self.BrokerID = data.__dict__['BrokerID'] self.FrontID = data.__dict__['FrontID'] self.SessionID = data.__dict__['SessionID'] self.__orderref = int(data.__dict__['MaxOrderRef']) lc.loger.info(data.__dict__) self.login_status = True log = data.__dict__['UserID'] + '交易服务器登陆成功' self.t.ReqSettlementInfoConfirm(self.BrokerID, self.Investor) # 对账单确认 else: self.login_status = False log = '登陆回报,错误代码:' + str( error.__dict__['ErrorID']) + ', 错误信息:' + str( error.__dict__['ErrorMsg']) self.put_log_event(log) def OnRspUserLogout(self, data, error, n, last): """登出回报""" lc.loger.info(threading.current_thread()) if error.__dict__['ErrorID'] == 0: self.login_status = False log = '交易服务器登出成功' else: self.login_status = True log = '登出回报,错误代码:' + str( error.__dict__['ErrorID']) + ', 错误信息:' + str( error.__dict__['ErrorMsg']) self.put_log_event(log) def onRspSettlementInfoConfirm(self, data, error, n, last): """确认结算信息回报""" log = '结算信息确认完成' self.put_log_event(log) time.sleep(1) self.getInstrument() # 查询合约资料 #self.short('rb1801',4422,1) #self.sell('rb1801',4431,1) #self.getPosition() def onRspQryInstrument(self, data, error, n, last): """ 合约查询回报 由于该回报的推送速度极快,因此不适合全部存入队列中处理, 选择先储存在一个本地字典中,全部收集完毕后再推送到队列中 (由于耗时过长目前使用其他进程读取) """ if error.__dict__['ErrorID'] == 0: event = Event(type_=EVENT_INSTRUMENT) event.dict_['data'] = data.__dict__ event.dict_['last'] = last self.__eventEngine.put(event) if last == True: time.sleep(2) self.t.ReqQryDepthMarketData() # 查询合约截面数据 else: log = '合约投资者回报,错误代码:' + str( error.__dict__['ErrorID']) + ', 错误信息:' + str( error.__dict__['ErrorMsg']) self.put_log_event(log) def onRspQryDepthMarketData(self, data, error, n, last): # 常规行情事件 event = Event(type_=EVENT_MARKETDATA) event.dict_['data'] = data.__dict__ event.dict_['last'] = last self.__eventEngine.put(event) def getInstrumentMarginRate(self, instrumentID): self.t.ReqQryInstrumentMarginRate( BrokerID=self.__brokerid, InvestorID=self.__userid, InstrumentID=instrumentID) # 查询合约保证金率 def OnRspQryInstrumentMarginRate(self, data, error, n, last): # 合约保证金 event = Event(type_=EVENT_INSTRUMENT_MAGIN_RATE) event.dict_['data'] = data.__dict__ event.dict_['last'] = last self.__eventEngine.put(event) def onRspQryInvestorPosition(self, data, error, n, last): """持仓查询回报""" if error.__dict__['ErrorID'] == 0: event = Event(type_=EVENT_POSITION) event.dict_['data'] = data.__dict__ event.dict_['last'] = last self.__eventEngine.put(event) else: log = ('持仓查询回报,错误代码:' + str(error.__dict__['ErrorID']) + ', 错误信息:' + str(error.__dict__['ErrorMsg'])) self.put_log_event(log) # ---------------------------------------------------------------------- def onRspQryTradingAccount(self, data, error, n, last): """资金账户查询回报""" if error.__dict__['ErrorID'] == 0: event = Event(type_=EVENT_ACCOUNT) event.dict_['data'] = data.__dict__ self.__eventEngine.put(event) else: log = ('账户查询回报,错误代码:' + str(error.__dict__['ErrorID']) + ', 错误信息:' + str(error.__dict__['ErrorMsg'])) self.put_log_event(log) def onRtnTrade(self, data): """成交回报""" # 常规成交事件 event1 = Event(type_=EVENT_TRADE) event1.dict_['data'] = data.__dict__ self.__eventEngine.put(event1) def onRtnOrder(self, data): """报单回报""" # 更新最大报单编号 newref = data.__dict__['OrderRef'] self.__orderref = max(self.__orderref, int(newref)) # 常规报单事件 event1 = Event(type_=EVENT_ORDER) event1.dict_['data'] = data.__dict__ self.__eventEngine.put(event1) def onRspOrderInsert(self, data, error, n, last): """发单错误(柜台)""" log = data.__dict__['InstrumentID'] + ' 发单错误回报,错误代码:' + str( error.__dict__['ErrorID']) + ', 错误信息:' + str( error.__dict__['ErrorMsg']) # self.put_log_event(log) lc.loger_order.info('onRspOrderInsert') lc.loger_error.info(log) lc.loger_order.info(data.__dict__) def onErrRtnOrderInsert(self, data, error): """发单错误回报(交易所)""" log = data.__dict__['InstrumentID'] + '发单错误回报,错误代码:' + str( error.__dict__['ErrorID']) + ', 错误信息:' + str( error.__dict__['ErrorMsg']) # self.put_log_event(log) lc.loger_error.info('onErrRtnOrderInsert') lc.loger_error.info(log) lc.loger_error.info(data.__dict__) def onRspError(self, error, n, last): """错误回报""" log = '交易错误回报,错误代码:' + str( error.__dict__['ErrorID']) + ', 错误信息:' + str( error.__dict__['ErrorMsg']) # self.put_log_event(log) lc.loger_error.info('onRspError') lc.loger_error.info(log) lc.loger_error.info(error.__dict__) # ---------------------------------------------------------------------- def onRspOrderAction(self, data, error, n, last): """撤单错误(柜台)""" log = '撤单错误回报,错误代码:' + str( error.__dict__['ErrorID']) + ', 错误信息:' + str( error.__dict__['ErrorMsg']) # self.put_log_event(log) lc.loger_error.info('onRspOrderAction') lc.loger_error.info(log) lc.loger_error.info(data.__dict__) # ---------------------------------------------------------------------- def onErrRtnOrderAction(self, data, error): """撤单错误回报(交易所)""" event = Event(type_=EVENT_LOG) log = data['合约代码'] + ' 撤单错误回报,错误代码:' + str( error.__dict__['ErrorID']) + ', 错误信息:' + str( error.__dict__['ErrorMsg']) event.dict_['log'] = log # self.__eventEngine.put(event) lc.loger_error.info('onErrRtnOrderAction') lc.loger_error.info(log) lc.loger_error.info(data.__dict__) def getInstrument(self): """查询合约""" self.__reqid = self.__reqid + 1 self.t.ReqQryInstrument() def getAccount(self): """查询账户""" self.__reqid = self.__reqid + 1 self.t.ReqQryTradingAccount(self.__brokerid, self.__userid) # ---------------------------------------------------------------------- def getPosition(self): """查询持仓""" self.__reqid = self.__reqid + 1 self.t.ReqQryInvestorPosition(self.__brokerid, self.__userid) def sendorder(self, instrumentid, price, vol, direction, offset): """发单""" self.__reqid = self.__reqid + 1 self.__orderref = self.__orderref + 1 # 限价 self.t.ReqOrderInsert( BrokerID=self.__brokerid, InvestorID=self.__userid, InstrumentID=instrumentid, OrderRef='{0:>12}'.format(self.__orderref), UserID=self.__userid, OrderPriceType=OrderPriceTypeType.LimitPrice, Direction=direction, CombOffsetFlag=offset, CombHedgeFlag=HedgeFlagType.Speculation.__char__(), LimitPrice=price, VolumeTotalOriginal=vol, TimeCondition=TimeConditionType.GFD, VolumeCondition=VolumeConditionType.AV, MinVolume=1, ForceCloseReason=ForceCloseReasonType.NotForceClose, ContingentCondition=ContingentConditionType.Immediately) return self.__orderref # 返回订单号,便于某些算法进行动态管理 # OrderPriceType--LimitPrice 限价单 # CombHedgeFlag--投机套保标记,默认投机单Speculation # TimeConditionType是一个有效期类型类型#当日有效--GFD # VolumeConditionType是一个成交量类型类型#任何数量--VolumeConditionType.AV # ContingentConditionType是一个触发条件类型,#立即ContingentConditionType.Immediately def buy(self, symbol, price, vol): # 买开多开 direction = DirectionType.Buy offset = OffsetFlagType.Open.__char__() self.sendorder(symbol, price, vol, direction, offset) def sell(self, symbol, price, vol): # 多平 direction = DirectionType.Sell offset = OffsetFlagType.Close.__char__() self.sendorder(symbol, price, vol, direction, offset) def selltoday(self, symbol, price, vol): # 平今多 direction = DirectionType.Sell offset = OffsetFlagType.CloseToday.__char__() self.sendorder(symbol, price, vol, direction, offset) def short(self, symbol, price, vol): # 卖开空开 direction = DirectionType.Sell offset = OffsetFlagType.Open.__char__() self.sendorder(symbol, price, vol, direction, offset) def cover(self, symbol, price, vol): # 空平 direction = DirectionType.Buy offset = OffsetFlagType.Close.__char__() self.sendorder(symbol, price, vol, direction, offset) def covertoday(self, symbol, price, vol): # 平今空 direction = DirectionType.Buy offset = OffsetFlagType.CloseToday.__char__() self.sendorder(symbol, price, vol, direction, offset) # ---------------------------------------------------------------------- # tmp["合约代码"] = var["InstrumentID"] # tmp["交易所代码"] = var["ExchangeID"] # tmp["报单引用"] = var["OrderRef"] # tmp["买卖方向"] = var["Direction"] # tmp["组合开平标志"] = var["CombOffsetFlag"] # tmp["价格"] = var["LimitPrice"] # tmp["数量"] = var["VolumeTotalOriginal"] # tmp["请求编号"] = var["RequestID"] # tmp["本地报单编号"] = var["OrderLocalID"] # tmp["报单编号"] = var["OrderSysID"] # tmp["今成交数量"] = var["VolumeTraded"] # tmp["剩余数量"] = var["VolumeTotal"] # tmp["报单日期"] = var["InsertDate"] # tmp["委托时间"] = var["InsertTime"] # tmp["前置编号"] = var["FrontID"] # tmp["会话编号"] = var["SessionID"] # tmp["状态信息"] = var["StatusMsg"] # tmp["序号"] = var["SequenceNo"] def cancelOrder(self, order): """撤单""" # lc.loger.info(order) self.__reqid = self.__reqid + 1 self.t.ReqOrderAction(BrokerID=self.__brokerid, InvestorID=self.__userid, OrderRef=order['OrderLocalID'], FrontID=int(order['FrontID']), SessionID=int(order['SessionID']), OrderSysID=order['OrderSysID'], ActionFlag=ActionFlagType.Delete, ExchangeID=order["ExchangeID"], InstrumentID=order['InstrumentID'])
class Test: def __init__(self, args): print(dt.datetime.today(), '---- __init__ ----') # self.rootdir = os.path.abspath(os.path.join(os.getcwd(), os.pardir)) self.rootdir = os.getcwd() # parse command line input args self.ProductClass2 = list() if args.product is None else [ x.upper() for x in args.product ] self.ExchangeID2 = list() if args.exchange is None else [ x.upper() for x in args.exchange ] self.ProductID2 = list() if args.underlying is None else [ x.upper() for x in args.underlying ] account = 'real_eb1' if args.account is None else args.account[0] self.mongodb = 'mongodb2' if args.mongodb is None else args.mongodb[0] # print(self.ProductClass2) # print(self.ExchangeID2) # print(self.ProductID2) # print(account) # print(mongodb) # ctp connection, current path is '...\PyCtp' config = SafeConfigParser() ctp_path = os.path.join(os.path.abspath('..'), 'PyShare', 'config', 'ctp_connection.ini') config.read(ctp_path) self.BrokerID = config.get(account, 'BrokerID') self.UserID = config.get(account, 'UserID') self.Password = config.get(account, 'Password') self.q_ip = config.get(account, 'q_ip') self.t_ip = config.get(account, 't_ip') self.Session = '' self.q = Quote() self.t = Trade() self.contract = list() self.contractdf = pd.DataFrame() self.TradingDay = '' # create connection to mongodb, make sure it is primary connection mongo_path = os.path.join(os.path.abspath('..'), 'PyShare', 'config', 'mongodb_connection.ini') self.mdb = Mongo.MongoDB(mongo_path) # run mongodb connection after user login confirmed, e.g., q_OnRspUserLogin(), OnRspUserLogin() # mdb_connection_result = self.mdb.connect(mongodb) # ----------------- quote related method ----------------- def q_OnFrontConnected(self): print(dt.datetime.today(), '---- q_OnFrontConnected ----') # when q_ip is reached, start user login, can be anonymous # self.q.ReqUserLogin(BrokerID=self.BrokerID, UserID=self.UserID, Password=self.Password) self.q.ReqUserLogin() def q_OnFrontDisconnected(self, nReason=int): print(dt.datetime.today(), '---- q_OnFrontDisconnected ----') # time.sleep(60) def q_OnRspUserLogin(self, pRspUserLogin=CThostFtdcRspUserLoginField, pRspInfo=CThostFtdcRspInfoField, nRequestID=int, bIsLast=bool): print(dt.datetime.today(), '---- q_OnRspUserLogin ----') # print(pRspUserLogin) # print(pRspInfo) # print(nRequestID) # print(bIsLast) if pRspInfo.getErrorID() == 0: print('OnRspUserLogin Successful', pRspInfo) self.mdb.connect(self.mongodb) self.TradingDay = pRspUserLogin.getTradingDay() self.contractdf = pd.read_csv( os.path.join(self.rootdir, 'contract.csv')) # print(self.contractdf) ff = pd.Series.repeat(pd.Series([True]), self.contractdf.shape[0]) p_idx = ff if len( self.ProductClass2 ) == 0 else self.contractdf['ProductClass2'].isin( self.ProductClass2) e_idx = ff if len(self.ExchangeID2 ) == 0 else self.contractdf['ExchangeID2'].isin( self.ExchangeID2) u_idx = ff if len( self.ProductID2) == 0 else self.contractdf['ProductID2'].isin( self.ProductID2) idx = [a and b and c for a, b, c in zip(p_idx, e_idx, u_idx)] gg = self.contractdf.loc[idx] print('ProductClass', self.ProductClass2) print('Exchange', self.ExchangeID2) print('Underlying', self.ProductID2) print('TradingDay', self.TradingDay) print(dt.datetime.today(), '---- total number of selected symbol', gg.shape[0], '----') if (not any(idx)): input('no matched symbols, press enter key to exit') sys.exit(2) else: print(dt.datetime.today(), '---- SubscribeMarketData ----') for index, row in gg.iterrows(): # print(row['InstrumentID'], row['Symbol']) # ** create index in mongodb for faster query, removed, using single python script instead ** # self.mdb.create_index_once(row['Symbol'], 'TradingDay', True) # case sensitive, e.g., IF1612 is not the same as if1612 self.q.SubscribeMarketData(row['InstrumentID']) print(dt.datetime.today(), '---- SubscribeMarketData finished ----') else: print('OnRspUserLogin Error', pRspInfo) def q_OnRtnDepthMarketData(self, pDepthMarketData=CThostFtdcDepthMarketDataField ): # print(dt.datetime.today(), '---- q_OnRtnDepthMarketData ----') # print(pDepthMarketData) tk = pDepthMarketData # ExchangeID --> ExchangeID2, InstrumentID --> Instrumentid2, e.g., Symbol = 'SHFE.CU1612' kk = self.contractdf.loc[self.contractdf['InstrumentID'] == tk.getInstrumentID()] cc = kk['Symbol'].values.tolist()[0] # convert TradingDay='20161115' to TradingDay='2016-11-15' format, e.g., _id = 2016-11-15 13:26:00 # dt.datetime.strptime(tk.getTradingDay(),'%Y%m%d').strftime('%Y-%m-%d') # ' '.join([dt.datetime.today().strftime('%Y-%m-%d'), tk.getUpdateTime()]) # dt.datetime.today().strftime('%Y-%m-%d %H:%M:%S.%f') # 'TradingDay':dt.datetime.strptime(tk.getTradingDay(),'%Y%m%d').strftime('%Y-%m-%d'), 'UpdateTime':tk.getUpdateTime(), 'UpdateMillisec':tk.getUpdateMillisec() # self.TradingDay = pRspUserLogin.getTradingDay(), use TradingDay from pRspUserLogin # print(self.TradingDay, tk.getTradingDay()) CTPTIME = pytz.timezone('Asia/Shanghai').localize( dt.datetime.strptime( ' '.join([ tk.getTradingDay(), tk.getUpdateTime(), str(tk.getUpdateMillisec()) ]), '%Y%m%d %H:%M:%S %f')) sdd = { '_id': dt.datetime.utcnow(), 'BID': tk.getBidPrice1(), 'ASK': tk.getAskPrice1(), 'BVOL': int(tk.getBidVolume1()), 'AVOL': int(tk.getAskVolume1()), 'LAST': tk.getLastPrice(), 'VOLUME': int(tk.getVolume()), 'OI': int(tk.getOpenInterest()), 'TradingDay': self.TradingDay, 'CTPTIME': CTPTIME } if sdd['BID'] > 1e32 and sdd['ASK'] > 1e32 and sdd[ 'BVOL'] == 0 and sdd['AVOL'] == 0: # do not record these points print('U', end='', flush=True) else: # price used for charting print('x', end='', flush=True) if sdd['BVOL'] > 0: sdd['PRICE'] = sdd['BID'] else: if sdd['AVOL'] > 0: sdd['PRICE'] = sdd['ASK'] else: if sdd['VOLUME'] > 0: sdd['PRICE'] = sdd['LAST'] else: sdd['PRICE'] = tk.getPreSettlementPrice() # check if a collection exists, upsert = update + insert, trust the latest data is the correct data, even if the previous data maybe correct result = self.mdb.upsert_dict(cc, sdd, '_id') def q_OnRspSubMarketData( self, pSpecificInstrument=CThostFtdcSpecificInstrumentField, pRspInfo=CThostFtdcRspInfoField, nRequestID=int, bIsLast=bool): # print(dt.datetime.today(), '---- q_OnRspSubMarketData ----') # print(pSpecificInstrument) # print(pRspInfo) # print(nRequestID) # print(bIsLast) pass def StartQuote(self): print(dt.datetime.today(), '---- CTP Quote ----') api = self.q.CreateApi() spi = self.q.CreateSpi() self.q.RegisterSpi(spi) self.q.OnFrontConnected = self.q_OnFrontConnected self.q.OnFrontDisconnected = self.q_OnFrontDisconnected self.q.OnRspUserLogin = self.q_OnRspUserLogin # market data subscription and return depth data self.q.OnRtnDepthMarketData = self.q_OnRtnDepthMarketData self.q.OnRspSubMarketData = self.q_OnRspSubMarketData # initiate connection to quote server self.q.RegCB() self.q.RegisterFront(self.q_ip) self.q.Init() self.q.Join() # ----------------- trade related method ----------------- def OnFrontConnected(self): print(dt.datetime.today(), '---- OnFrontConnected ----') self.t.ReqUserLogin(BrokerID=self.BrokerID, UserID=self.UserID, Password=self.Password) def OnFrontDisconnected(self, nReason=int): print(dt.datetime.today(), '---- OnFrontDisconnected ----') # time.sleep(60) def OnRspUserLogin(self, pRspUserLogin=CThostFtdcRspUserLoginField, pRspInfo=CThostFtdcRspInfoField, nRequestID=int, bIsLast=bool): print(dt.datetime.today(), '---- OnRspUserLogin ----') # print(pRspUserLogin) # print(pRspInfo) # print(nRequestID) # print(bIsLast) if pRspInfo.getErrorID() == 0: print('OnRspUserLogin Successful', pRspInfo) self.mdb.connect(self.mongodb) self.Session = pRspUserLogin.getSessionID() self.t.ReqSettlementInfoConfirm(BrokerID=self.BrokerID, InvestorID=self.UserID) self.TradingDay = pRspUserLogin.getTradingDay() else: print('OnRspUserLogin Error', pRspInfo) def OnRspUserLogout(self, pUserLogout=CThostFtdcUserLogoutField, pRspInfo=CThostFtdcRspInfoField, nRequestID=int, bIsLast=bool): print(dt.datetime.today(), '---- OnRspUserLogout ----') # print(pUserLogout) # print(pRspInfo) # print(nRequestID) # print(bIsLast) def OnRtnOrder(self, pOrder=CThostFtdcOrderField): # print(dt.datetime.today(), '---- OnRtnOrder ----') # print(pOrder) pass def OnErrRtnOrderInsert(self, pInputOrder=CThostFtdcInputOrderField, pRspInfo=CThostFtdcRspInfoField): # print(dt.datetime.today(), '---- OnErrRtnOrderInsert ----') # print(pInputOrder) # print(pRspInfo) pass def OnErrRtnOrderAction(self, pOrderAction=CThostFtdcOrderActionField, pRspInfo=CThostFtdcRspInfoField): # print(dt.datetime.today(), '---- OnErrRtnOrderAction ----') # print(pOrderAction) # print(pRspInfo) pass def OnRtnTrade(self, pTrade=CThostFtdcTradeField): # print(dt.datetime.today(), '---- OnRtnTrade ----') # print(pTrade) pass def OnRtnQueryBankBalanceByFuture( self, pNotifyQueryAccount=CThostFtdcNotifyQueryAccountField): # print(dt.datetime.today(), '---- OnRtnQueryBankBalanceByFuture ----') # print(pNotifyQueryAccount) pass def OnRtnFromBankToFutureByFuture(self, pRspTransfer=CThostFtdcRspTransferField): # print(dt.datetime.today(), '---- OnRtnFromBankToFutureByFuture ----') # print(pRspTransfer) pass def OnRtnFromFutureToBankByFuture(self, pRspTransfer=CThostFtdcRspTransferField): # print(dt.datetime.today(), '---- OnRtnFromFutureToBankByFuture ----') # print(pRspTransfer) pass def OnRtnTradingNotice(self, pTradingNoticeInfo=CThostFtdcTradingNoticeInfoField ): # print(dt.datetime.today(), '---- OnRtnTradingNotice ----') # print(pTradingNoticeInfo) pass def OnRtnInstrumentStatus(self, pInstrumentStatus=CThostFtdcInstrumentStatusField ): # print(dt.datetime.today(), '---- OnRtnInstrumentStatus ----') # print(pInstrumentStatus) pass def OnRspSettlementInfoConfirm( self, pSettlementInfoConfirm=CThostFtdcSettlementInfoConfirmField, pRspInfo=CThostFtdcRspInfoField, nRequestID=int, bIsLast=bool): print(dt.datetime.today(), '---- OnRspSettlementInfoConfirm ----') # print(pSettlementInfoConfirm) # print(pRspInfo) # print(nRequestID) # print(bIsLast) self.t.ReqQryInstrument() def OnRspQryInstrument(self, pInstrument=CThostFtdcInstrumentField, pRspInfo=CThostFtdcRspInfoField, nRequestID=int, bIsLast=bool): # print(dt.datetime.today(), '---- OnRspQryInstrument ----') # if pInstrument.getInstrumentID()=='SR709C7000' or pInstrument.getInstrumentID()=='m1709-P-2800': # print(pInstrument) # print(pRspInfo) # print(nRequestID) # print(bIsLast) # StartQuote after getting all the contract information, ctp InstrumentID has a mixture of upper and lower case # contract definition, * is not used # exchange, underlying, contract, expiration # [base]: base_exchange, base_underlying(*), base_contract # [pricing]: pricing_exchange, pricing_underlying(*), pricing_contract # [hedging]: hedging_exchange, hedging_underlying(*), hedging_contract mm = [ pInstrument.getInstrumentID(), pInstrument.getExchangeID(), pInstrument.getProductID(), str(pInstrument.getProductClass()).split('.')[1], pInstrument.getExchangeID(), pInstrument.getUnderlyingInstrID() ] nn = [x.upper() for x in mm] tt = [pInstrument.getPriceTick(), pInstrument.getExpireDate()] self.contract.append(mm + nn + tt) if bIsLast: print(dt.datetime.today(), '---- OnRspQryInstrument Completed ----') self.contractdf = pd.DataFrame( self.contract, columns=[ 'InstrumentID', 'ExchangeID', 'ProductID', 'ProductClass', 'UnderlyingExchangeID', 'UnderlyingInstrID', 'InstrumentID2', 'ExchangeID2', 'ProductID2', 'ProductClass2', 'UnderlyingExchangeID2', 'UnderlyingInstrID2', 'PriceTick', 'ExpireDate' ]) sg = self.contractdf[['ExchangeID2', 'InstrumentID2']] self.contractdf['Symbol'] = [ '.'.join(x) for x in sg.values.tolist() ] # change CZCE SRC and SRP underlying symbol to SR_O, may extend this list in the future idx = [ row['ExchangeID2'] == 'CZCE' and row['ProductID2'] in ['SRC', 'SRP'] for index, row in self.contractdf.iterrows() ] self.contractdf.loc[idx, 'ProductID'] = 'SR_O' self.contractdf.loc[idx, 'ProductID2'] = 'SR_O' # export to a csv file, so it can be read by market data quote functions self.contractdf.to_csv(os.path.join(self.rootdir, 'contract.csv'), index=False) self.contract = list() print(dt.datetime.today(), '---- total number of ctp symbol', self.contractdf.shape[0], '----') # self.StartQuote() def Run(self): print(dt.datetime.today(), '---- CTP Trade ----') api = self.t.CreateApi() spi = self.t.CreateSpi() self.t.RegisterSpi(spi) # rewrite default api interface self.t.OnFrontConnected = self.OnFrontConnected self.t.OnFrontDisconnected = self.OnFrontDisconnected self.t.OnRspUserLogin = self.OnRspUserLogin self.t.OnRspUserLogout = self.OnRspUserLogout # have to confirm settlement result before moving to the next step # run self.StartQuote() after settlement information is confirmed self.t.OnRspSettlementInfoConfirm = self.OnRspSettlementInfoConfirm # order related self.t.OnRtnOrder = self.OnRtnOrder self.t.OnErrRtnOrderInsert = self.OnErrRtnOrderInsert self.t.OnErrRtnOrderAction = self.OnErrRtnOrderAction self.t.OnRtnTrade = self.OnRtnTrade # FCM bank transfer, trading notice self.t.OnRtnQueryBankBalanceByFuture = self.OnRtnQueryBankBalanceByFuture self.t.OnRtnFromBankToFutureByFuture = self.OnRtnFromBankToFutureByFuture self.t.OnRtnFromFutureToBankByFuture = self.OnRtnFromFutureToBankByFuture self.t.OnRtnTradingNotice = self.OnRtnTradingNotice # get underlying (a.k.a instrument) status self.t.OnRtnInstrumentStatus = self.OnRtnInstrumentStatus # return contract information self.t.OnRspQryInstrument = self.OnRspQryInstrument # initiate connection to trade server self.t.RegCB() self.t.RegisterFront(self.t_ip) self.t.Init() self.t.Join()