From d1f196a4aa6752afd35462e0aa887b2729a4d83c Mon Sep 17 00:00:00 2001 From: chenxy123 Date: Mon, 12 Dec 2016 22:52:39 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90QDP=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../settings/Windows Azure Subscriptions.xml | 2 +- vn.qdp/vnqdpmd/vnqdpmd/vnqdpmd.cpp | 1 - vn.qdp/vnqdpmd/vnqdpmd/vnqdpmd.vcxproj | 8 +- .../vnqdpmd/vnqdpmd/vnqdpmd.vcxproj.filters | 8 +- .../settings/Windows Azure Subscriptions.xml | 2 +- vn.qdp/vnqdptd/vnqdptd/vnqdptd.vcxproj | 16 +- .../vnqdptd/vnqdptd/vnqdptd.vcxproj.filters | 16 +- vn.trader/qdpGateway/qdpGateway.py | 882 +++++++++--------- vn.trader/qdpGateway/vnqdpmd.pyd | Bin 300032 -> 300032 bytes vn.trader/qdpGateway/vnqdptd.pyd | Bin 462848 -> 462848 bytes vn.trader/shzdGateway/shzdGateway.py | 1 - 11 files changed, 465 insertions(+), 471 deletions(-) diff --git a/vn.qdp/vnqdpmd/Visual Studio 2013/settings/Windows Azure Subscriptions.xml b/vn.qdp/vnqdpmd/Visual Studio 2013/settings/Windows Azure Subscriptions.xml index cacd03c2..49ea0043 100644 --- a/vn.qdp/vnqdpmd/Visual Studio 2013/settings/Windows Azure Subscriptions.xml +++ b/vn.qdp/vnqdpmd/Visual Studio 2013/settings/Windows Azure Subscriptions.xml @@ -1,5 +1,5 @@ - AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAAyRIhRmRN8UK7w5RuPHePCQAAAAACAAAAAAAQZgAAAAEAACAAAACQk+guh+ywWR7iJKHx4q/rl8GJs1w1kHOBDxLxLwyRwQAAAAAOgAAAAAIAACAAAABPgLw+AuxePq11TX16PdB1NyHEqJD1OGjxXDrk6zI58BAAAABDp/NWkif0PpHu24ZiWNDpQAAAAD6czV67awJHJ1Lad1N571p8XaKpngFM3+M/dUiuA7rb48Ig57TRmOwHTcx9xbSoJ+NTqxs+B47Ro2YPRnS43xc= + AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAAyRIhRmRN8UK7w5RuPHePCQAAAAACAAAAAAAQZgAAAAEAACAAAAChADhs2/yOAe5Vk4jrTcDim0CaDy9YY+o9lhRguoeP0wAAAAAOgAAAAAIAACAAAAAOB6PCBww/fcrV5HJqxMRvxrEecaNTZTGxqhs9412B4xAAAAB7qrpwNcKNMR4DD2O4atz6QAAAACwNgHEKJoRYjwYImBMY1oeq3bWFGTEUA5QJ+KK26sC2YlGfFqLb8g70FZnPfIGieZYSl8sYVTiFo4hAwyODdro= \ No newline at end of file diff --git a/vn.qdp/vnqdpmd/vnqdpmd/vnqdpmd.cpp b/vn.qdp/vnqdpmd/vnqdpmd/vnqdpmd.cpp index 1c4a1514..7fcaa01b 100644 --- a/vn.qdp/vnqdpmd/vnqdpmd/vnqdpmd.cpp +++ b/vn.qdp/vnqdpmd/vnqdpmd/vnqdpmd.cpp @@ -904,7 +904,6 @@ int MdApi::exit() //该函数在原生API里没有,用于安全退出API用,原生的join似乎不太稳定 this->api->RegisterSpi(NULL); this->api->Release(); -// this->api->Join(); this->api = NULL; return 1; }; diff --git a/vn.qdp/vnqdpmd/vnqdpmd/vnqdpmd.vcxproj b/vn.qdp/vnqdpmd/vnqdpmd/vnqdpmd.vcxproj index 8fa6c56c..a833f095 100644 --- a/vn.qdp/vnqdpmd/vnqdpmd/vnqdpmd.vcxproj +++ b/vn.qdp/vnqdpmd/vnqdpmd/vnqdpmd.vcxproj @@ -107,12 +107,12 @@ - - + + - - + + diff --git a/vn.qdp/vnqdpmd/vnqdpmd/vnqdpmd.vcxproj.filters b/vn.qdp/vnqdpmd/vnqdpmd/vnqdpmd.vcxproj.filters index 3166208d..3c44bcbd 100644 --- a/vn.qdp/vnqdpmd/vnqdpmd/vnqdpmd.vcxproj.filters +++ b/vn.qdp/vnqdpmd/vnqdpmd/vnqdpmd.vcxproj.filters @@ -52,18 +52,18 @@ - + Resource Files - + Resource Files - + Resource Files - + Resource Files diff --git a/vn.qdp/vnqdptd/Visual Studio 2013/settings/Windows Azure Subscriptions.xml b/vn.qdp/vnqdptd/Visual Studio 2013/settings/Windows Azure Subscriptions.xml index 7f67c580..eb0d97b3 100644 --- a/vn.qdp/vnqdptd/Visual Studio 2013/settings/Windows Azure Subscriptions.xml +++ b/vn.qdp/vnqdptd/Visual Studio 2013/settings/Windows Azure Subscriptions.xml @@ -1,5 +1,5 @@ - AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAAyRIhRmRN8UK7w5RuPHePCQAAAAACAAAAAAAQZgAAAAEAACAAAAAAl4/w4VyqjUA3HilyerwjMwA8XWYuFqc0TymfwFacrgAAAAAOgAAAAAIAACAAAAA70M9sM2rW/I2svTmUIna/CghrIcaZufLj9Cra+3ylJRAAAABdxANXJfXRyoQazkSdgBYkQAAAAOmsd+eZrQTZXzPUzzcUIgIQDnT2hVaEGUrkkSKoTBipziykhRHEZOhlPWbHeZvg4aiJQcT7GeYyqyYKHBbl+aw= + AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAAyRIhRmRN8UK7w5RuPHePCQAAAAACAAAAAAAQZgAAAAEAACAAAACxOAY/ulOgIdKvYR/ZQqTfqRah3JAQMxXe+X25cv2+JwAAAAAOgAAAAAIAACAAAABCto2lfkqcOVxEbw8DDKUJp07D/UYM7fyE7OKy8TTaPhAAAADmLpTeNvhPv+/WFM0Tz/gLQAAAABK/J1c7r+qPkhqb66sIkaBRRnG9xXxu4mDv7XDJzpbEL2Ovv4sW1Fc0nAtb+9TLNb0RcXcBPqgi0IAZVbWOzWg= \ No newline at end of file diff --git a/vn.qdp/vnqdptd/vnqdptd/vnqdptd.vcxproj b/vn.qdp/vnqdptd/vnqdptd/vnqdptd.vcxproj index e4f49b84..34911d70 100644 --- a/vn.qdp/vnqdptd/vnqdptd/vnqdptd.vcxproj +++ b/vn.qdp/vnqdptd/vnqdptd/vnqdptd.vcxproj @@ -83,10 +83,10 @@ - - - - + + + + @@ -107,12 +107,12 @@ - - + + - - + + diff --git a/vn.qdp/vnqdptd/vnqdptd/vnqdptd.vcxproj.filters b/vn.qdp/vnqdptd/vnqdptd/vnqdptd.vcxproj.filters index 2b482c11..7af1bdfc 100644 --- a/vn.qdp/vnqdptd/vnqdptd/vnqdptd.vcxproj.filters +++ b/vn.qdp/vnqdptd/vnqdptd/vnqdptd.vcxproj.filters @@ -27,16 +27,16 @@ Header Files - + Header Files - + Header Files - + Header Files - + Header Files @@ -52,18 +52,18 @@ - + Resource Files - + Resource Files - + Resource Files - + Resource Files diff --git a/vn.trader/qdpGateway/qdpGateway.py b/vn.trader/qdpGateway/qdpGateway.py index b3e3d3a6..2d3d189d 100644 --- a/vn.trader/qdpGateway/qdpGateway.py +++ b/vn.trader/qdpGateway/qdpGateway.py @@ -83,9 +83,9 @@ class QdpGateway(VtGateway): def connect(self): """杩炴帴""" # 杞藉叆json鏂囦欢 - fileName = self.gatewayName + '_connect.json' - path = os.path.abspath(os.path.dirname(__file__)) - fileName = os.path.join(path, fileName) + fileName = self.gatewayName + '_connect.json' + path = os.path.abspath(os.path.dirname(__file__)) + fileName = os.path.join(path, fileName) try: f = file(fileName) @@ -114,7 +114,7 @@ class QdpGateway(VtGateway): # 鍒涘缓琛屾儏鍜屼氦鏄撴帴鍙e璞 self.mdApi.connect(userID, password, brokerID, mdAddress) self.tdApi.connect(userID, password, brokerID, tdAddress) - + # 鍒濆鍖栧苟鍚姩鏌ヨ self.initQuery() @@ -146,10 +146,7 @@ class QdpGateway(VtGateway): #---------------------------------------------------------------------- def close(self): """鍏抽棴""" - if self.mdConnected: - self.mdApi.close() - if self.tdConnected: - self.tdApi.close() + pass #---------------------------------------------------------------------- def initQuery(self): @@ -280,173 +277,173 @@ class QdpMdApi(MdApi): #---------------------------------------------------------------------- def close(self): """鍏抽棴""" - self.logout() + self.logout() self.exit() #---------------------------------------------------------------------- def onFrontConnected(self): - """鏈嶅姟鍣ㄨ繛鎺""" - self.connectionStatus = True + """鏈嶅姟鍣ㄨ繛鎺""" + self.connectionStatus = True - log = VtLogData() - log.gatewayName = self.gatewayName - log.logContent = u'琛屾儏鏈嶅姟鍣ㄨ繛鎺ユ垚鍔' - self.gateway.onLog(log) - self.login() + log = VtLogData() + log.gatewayName = self.gatewayName + log.logContent = u'琛屾儏鏈嶅姟鍣ㄨ繛鎺ユ垚鍔' + self.gateway.onLog(log) + self.login() #---------------------------------------------------------------------- def onFrontDisconnected(self, i): - """鏈嶅姟鍣ㄦ柇寮""" - self.connectionStatus = False - self.loginStatus = False - self.gateway.mdConnected = False + """鏈嶅姟鍣ㄦ柇寮""" + self.connectionStatus = False + self.loginStatus = False + self.gateway.mdConnected = False - log = VtLogData() - log.gatewayName = self.gatewayName - log.logContent = u'琛屾儏鏈嶅姟鍣ㄨ繛鎺ユ柇寮' - self.gateway.onLog(log) + log = VtLogData() + log.gatewayName = self.gatewayName + log.logContent = u'琛屾儏鏈嶅姟鍣ㄨ繛鎺ユ柇寮' + self.gateway.onLog(log) #---------------------------------------------------------------------- def onHeartBeatWarning(self, i): - """""" - pass + """""" + pass #---------------------------------------------------------------------- def onPackageStart(self, topicID, sequenceNo): - """""" - pass + """""" + pass #---------------------------------------------------------------------- def onPackageEnd(self, topicID, sequenceNo): - """""" - pass + """""" + pass #---------------------------------------------------------------------- def onMultiHeartbeat(self, currTime, multiCastIP): - """""" - pass + """""" + pass #---------------------------------------------------------------------- def udpMarketData(self, data): - """""" - pass + """""" + pass #---------------------------------------------------------------------- def onRspError(self, error, id, last): - """閿欒鍥炴姤""" - err = VtErrorData() - err.gatewayName = self.gatewayName - err.errorID = error['ErrorID'] - err.errorMsg = error['ErrorMsg'].decode('gbk') - self.gateway.onError(err) + """閿欒鍥炴姤""" + err = VtErrorData() + err.gatewayName = self.gatewayName + err.errorID = error['ErrorID'] + err.errorMsg = error['ErrorMsg'].decode('gbk') + self.gateway.onError(err) #---------------------------------------------------------------------- def onRspUserLogin(self, data, error, id, last): - """鐧婚檰鍥炴姤""" - # 濡傛灉鐧诲綍鎴愬姛锛屾帹閫佹棩蹇椾俊鎭 - if error['ErrorID'] == 0: - self.loginStatus = True - self.gateway.mdConnected = True + """鐧婚檰鍥炴姤""" + # 濡傛灉鐧诲綍鎴愬姛锛屾帹閫佹棩蹇椾俊鎭 + if error['ErrorID'] == 0: + self.loginStatus = True + self.gateway.mdConnected = True - log = VtLogData() - log.gatewayName = self.gatewayName - log.logContent = u'琛屾儏鏈嶅姟鍣ㄧ櫥褰曞畬鎴' - self.gateway.onLog(log) + log = VtLogData() + log.gatewayName = self.gatewayName + log.logContent = u'琛屾儏鏈嶅姟鍣ㄧ櫥褰曞畬鎴' + self.gateway.onLog(log) - # 閲嶆柊璁㈤槄涔嬪墠璁㈤槄鐨勫悎绾 - for subscribeReq in self.subscribedSymbols: - self.subscribe(subscribeReq) + # 閲嶆柊璁㈤槄涔嬪墠璁㈤槄鐨勫悎绾 + for subscribeReq in self.subscribedSymbols: + self.subscribe(subscribeReq) - # 鍚﹀垯锛屾帹閫侀敊璇俊鎭 - else: - err = VtErrorData() - err.gatewayName = self.gatewayName - err.errorID = error['ErrorID'] - err.errorMsg = error['ErrorMsg'].decode('gbk') - self.gateway.onError(err) + # 鍚﹀垯锛屾帹閫侀敊璇俊鎭 + else: + err = VtErrorData() + err.gatewayName = self.gatewayName + err.errorID = error['ErrorID'] + err.errorMsg = error['ErrorMsg'].decode('gbk') + self.gateway.onError(err) #---------------------------------------------------------------------- def onRspUserLogout(self, data, error, id, last): - """鐧诲嚭鍥炴姤""" - # 濡傛灉鐧诲嚭鎴愬姛锛屾帹閫佹棩蹇椾俊鎭 - if error['ErrorID'] == 0: - self.loginStatus = False - self.gateway.mdConnected = False + """鐧诲嚭鍥炴姤""" + # 濡傛灉鐧诲嚭鎴愬姛锛屾帹閫佹棩蹇椾俊鎭 + if error['ErrorID'] == 0: + self.loginStatus = False + self.gateway.mdConnected = False - log = VtLogData() - log.gatewayName = self.gatewayName - log.logContent = u'琛屾儏鏈嶅姟鍣ㄧ櫥鍑哄畬鎴' - self.gateway.onLog(log) + log = VtLogData() + log.gatewayName = self.gatewayName + log.logContent = u'琛屾儏鏈嶅姟鍣ㄧ櫥鍑哄畬鎴' + self.gateway.onLog(log) - # 鍚﹀垯锛屾帹閫侀敊璇俊鎭 - else: - err = VtErrorData() - err.gatewayName = self.gatewayName - err.errorID = error['ErrorID'] - err.errorMsg = error['ErrorMsg'].decode('gbk') - self.gateway.onError(err) + # 鍚﹀垯锛屾帹閫侀敊璇俊鎭 + else: + err = VtErrorData() + err.gatewayName = self.gatewayName + err.errorID = error['ErrorID'] + err.errorMsg = error['ErrorMsg'].decode('gbk') + self.gateway.onError(err) #---------------------------------------------------------------------- def onRtnQmdInstrumentStatu(self, data): - """""" - pass + """""" + pass #---------------------------------------------------------------------- def onRspSubscribeTopic(self, data, error, id, last): - """""" - pass + """""" + pass #---------------------------------------------------------------------- def onRspQryTopic(self, data, error, id, last): - """""" - pass + """""" + pass #---------------------------------------------------------------------- def onRtnDepthMarketData(self, data): - """琛屾儏鎺ㄩ""" - tick = VtTickData() - tick.gatewayName = self.gatewayName + """琛屾儏鎺ㄩ""" + tick = VtTickData() + tick.gatewayName = self.gatewayName - tick.symbol = data['InstrumentID'] - tick.exchange = exchangeMapReverse.get(data['ExchangeID'], u'鏈煡') - tick.vtSymbol = tick.symbol #'.'.join([tick.symbol, EXCHANGE_UNKNOWN]) + tick.symbol = data['InstrumentID'] + tick.exchange = exchangeMapReverse.get(data['ExchangeID'], u'鏈煡') + tick.vtSymbol = tick.symbol #'.'.join([tick.symbol, EXCHANGE_UNKNOWN]) - tick.lastPrice = data['LastPrice'] - tick.volume = data['Volume'] - tick.openInterest = data['OpenInterest'] - tick.time = '.'.join([data['UpdateTime'], str(data['UpdateMillisec']/100)]) - tick.date = data['TradingDay'] + tick.lastPrice = data['LastPrice'] + tick.volume = data['Volume'] + tick.openInterest = data['OpenInterest'] + tick.time = '.'.join([data['UpdateTime'], str(data['UpdateMillisec']/100)]) + tick.date = data['TradingDay'] - tick.openPrice = data['OpenPrice'] - tick.highPrice = data['HighestPrice'] - tick.lowPrice = data['LowestPrice'] - tick.preClosePrice = data['PreClosePrice'] + tick.openPrice = data['OpenPrice'] + tick.highPrice = data['HighestPrice'] + tick.lowPrice = data['LowestPrice'] + tick.preClosePrice = data['PreClosePrice'] - tick.upperLimit = data['UpperLimitPrice'] - tick.lowerLimit = data['LowerLimitPrice'] + tick.upperLimit = data['UpperLimitPrice'] + tick.lowerLimit = data['LowerLimitPrice'] - # QDP鍙湁涓妗h鎯 - tick.bidPrice1 = data['BidPrice1'] - tick.bidVolume1 = data['BidVolume1'] - tick.askPrice1 = data['AskPrice1'] - tick.askVolume1 = data['AskVolume1'] + # QDP鍙湁涓妗h鎯 + tick.bidPrice1 = data['BidPrice1'] + tick.bidVolume1 = data['BidVolume1'] + tick.askPrice1 = data['AskPrice1'] + tick.askVolume1 = data['AskVolume1'] - self.gateway.onTick(tick) + self.gateway.onTick(tick) #---------------------------------------------------------------------- def onRspSubMarketData(self, data, error, id, last): - """""" - pass + """""" + pass #---------------------------------------------------------------------- def onRspUnSubMarketData(self, data, error, id, last): - """""" - pass + """""" + pass #---------------------------------------------------------------------- def onRspQryDepthMarketData(self, data, error, id, last): - """""" - pass + """""" + pass ######################################################################## @@ -462,7 +459,7 @@ class QdpTdApi(TdApi): self.gatewayName = gateway.gatewayName # gateway瀵硅薄鍚嶇О self.reqID = EMPTY_INT # 鎿嶄綔璇锋眰缂栧彿 - self.orderRef = EMPTY_INT # 璁㈠崟缂栧彿 + self.orderRef = EMPTY_INT # 璁㈠崟缂栧彿 self.connectionStatus = False # 杩炴帴鐘舵 self.loginStatus = False # 鐧诲綍鐘舵 @@ -494,8 +491,8 @@ class QdpTdApi(TdApi): os.makedirs(path) self.createFtdcTraderApi(path) - self.subscribePrivateTopic(0) - self.subscribePublicTopic(2) + self.subscribePrivateTopic(0) + self.subscribePublicTopic(0) # 娉ㄥ唽鏈嶅姟鍣ㄥ湴鍧 self.registerFront(self.address) @@ -535,11 +532,10 @@ class QdpTdApi(TdApi): def qryAccount(self): """鏌ヨ璐︽埛""" self.reqID += 1 - req = {} - req['UserID'] = self.userID - req['BrokerID'] = self.brokerID - req['InvestorID'] = self.investorID - self.reqQryInvestorAccount({}, self.reqID) + req = {} + req['BrokerID'] = self.brokerID + req['InvestorID'] = self.investorID + self.reqQryInvestorAccount(req, self.reqID) #---------------------------------------------------------------------- def qryPosition(self): @@ -573,12 +569,12 @@ class QdpTdApi(TdApi): req['UserID'] = self.userID req['InvestorID'] = self.investorID req['BrokerID'] = self.brokerID - req['HedgeFlag'] = defineDict['QDP_FTDC_CHF_Speculation'] # 鎶曟満鍗 - req['ForceCloseReason'] = defineDict['QDP_FTDC_FCR_NotForceClose'] # 闈炲己骞 - req['IsAutoSuspend'] = 0 # 闈炶嚜鍔ㄦ寕璧 - req['TimeCondition'] = defineDict['QDP_FTDC_TC_GFD'] # 浠婃棩鏈夋晥 - req['VolumeCondition'] = defineDict['QDP_FTDC_VC_AV'] # 浠绘剰鎴愪氦閲 - req['MinVolume'] = 1 # 鏈灏忔垚浜ら噺涓1 + req['HedgeFlag'] = defineDict['QDP_FTDC_CHF_Speculation'] # 鎶曟満鍗 + req['ForceCloseReason'] = defineDict['QDP_FTDC_FCR_NotForceClose'] # 闈炲己骞 + req['IsAutoSuspend'] = 0 # 闈炶嚜鍔ㄦ寕璧 + req['TimeCondition'] = defineDict['QDP_FTDC_TC_GFD'] # 浠婃棩鏈夋晥 + req['VolumeCondition'] = defineDict['QDP_FTDC_VC_AV'] # 浠绘剰鎴愪氦閲 + req['MinVolume'] = 1 # 鏈灏忔垚浜ら噺涓1 # 鍒ゆ柇FAK鍜孎OK if orderReq.priceType == PRICETYPE_FAK: @@ -600,7 +596,7 @@ class QdpTdApi(TdApi): def cancelOrder(self, cancelOrderReq): """鎾ゅ崟""" self.reqID += 1 - self.orderRef += 1 + self.orderRef += 1 req = {} @@ -621,491 +617,491 @@ class QdpTdApi(TdApi): #---------------------------------------------------------------------- def close(self): """鍏抽棴""" - self.logout() + self.logout() self.exit() #---------------------------------------------------------------------- def onFrontConnected(self): - """鏈嶅姟鍣ㄨ繛鎺""" - self.connectionStatus = True + """鏈嶅姟鍣ㄨ繛鎺""" + self.connectionStatus = True - log = VtLogData() - log.gatewayName = self.gatewayName - log.logContent = u'浜ゆ槗鏈嶅姟鍣ㄨ繛鎺ユ垚鍔' - self.gateway.onLog(log) + log = VtLogData() + log.gatewayName = self.gatewayName + log.logContent = u'浜ゆ槗鏈嶅姟鍣ㄨ繛鎺ユ垚鍔' + self.gateway.onLog(log) - self.login() + self.login() #---------------------------------------------------------------------- def onFrontDisconnected(self, i): - """鏈嶅姟鍣ㄦ柇寮""" - self.connectionStatus = False - self.loginStatus = False - self.gateway.tdConnected = False + """鏈嶅姟鍣ㄦ柇寮""" + self.connectionStatus = False + self.loginStatus = False + self.gateway.tdConnected = False - log = VtLogData() - log.gatewayName = self.gatewayName - log.logContent = u'浜ゆ槗鏈嶅姟鍣ㄨ繛鎺ユ柇寮' - self.gateway.onLog(log) + log = VtLogData() + log.gatewayName = self.gatewayName + log.logContent = u'浜ゆ槗鏈嶅姟鍣ㄨ繛鎺ユ柇寮' + self.gateway.onLog(log) #---------------------------------------------------------------------- def onHeartBeatWarning(self, i): - """""" - pass + """""" + pass #---------------------------------------------------------------------- def onPackageStart(self, topicID, sequenceNo): - """""" - pass + """""" + pass #---------------------------------------------------------------------- def onPackageEnd(self, topicID, sequenceNo): - """""" - pass + """""" + pass #---------------------------------------------------------------------- def onRspError(self, error, id, last): - """閿欒鍥炴姤""" - err = VtErrorData() - err.gatewayName = self.gatewayName - err.errorID = error['ErrorID'] - err.errorMsg = error['ErrorMsg'].decode('gbk') - self.gateway.onError(err) + """閿欒鍥炴姤""" + err = VtErrorData() + err.gatewayName = self.gatewayName + err.errorID = error['ErrorID'] + err.errorMsg = error['ErrorMsg'].decode('gbk') + self.gateway.onError(err) #---------------------------------------------------------------------- def onRspUserLogin(self, data, error, id, last): - """鐧婚檰鍥炴姤""" - # 濡傛灉鐧诲綍鎴愬姛锛屾帹閫佹棩蹇椾俊鎭 - if error['ErrorID'] == 0: - self.frontID = str(data['FrontID']) - self.sessionID = str(data['SessionID']) - self.loginStatus = True - self.gateway.tdConnected = True + """鐧婚檰鍥炴姤""" + # 濡傛灉鐧诲綍鎴愬姛锛屾帹閫佹棩蹇椾俊鎭 + if error['ErrorID'] == 0: + self.frontID = str(data['FrontID']) + self.sessionID = str(data['SessionID']) + self.loginStatus = True + self.gateway.tdConnected = True - log = VtLogData() - log.gatewayName = self.gatewayName - log.logContent = u'浜ゆ槗鏈嶅姟鍣ㄧ櫥褰曞畬鎴' - self.gateway.onLog(log) + log = VtLogData() + log.gatewayName = self.gatewayName + log.logContent = u'浜ゆ槗鏈嶅姟鍣ㄧ櫥褰曞畬鎴' + self.gateway.onLog(log) - # 鑾峰彇investorID - self.reqID += 1 - req = {} - req['UserID'] = self.userID - req['Password'] = self.password - req['BrokerID'] = self.brokerID - self.reqQryUserInvestor(req,self.reqID) + # 鑾峰彇investorID + self.reqID += 1 + req = {} + req['UserID'] = self.userID + req['Password'] = self.password + req['BrokerID'] = self.brokerID + self.reqQryUserInvestor(req,self.reqID) - # 鍚﹀垯锛屾帹閫侀敊璇俊鎭 - else: - err = VtErrorData() - err.gatewayName = self.gatewayName - err.errorID = error['ErrorID'] - err.errorMsg = error['ErrorMsg'].decode('gbk') - self.gateway.onError(err) + # 鍚﹀垯锛屾帹閫侀敊璇俊鎭 + else: + err = VtErrorData() + err.gatewayName = self.gatewayName + err.errorID = error['ErrorID'] + err.errorMsg = error['ErrorMsg'].decode('gbk') + self.gateway.onError(err) #---------------------------------------------------------------------- def onRspUserLogout(self, data, error, id, last): - """鐧诲嚭鍥炴姤""" - # 濡傛灉鐧诲嚭鎴愬姛锛屾帹閫佹棩蹇椾俊鎭 - if error['ErrorID'] == 0: - self.loginStatus = False - self.gateway.tdConnected = False + """鐧诲嚭鍥炴姤""" + # 濡傛灉鐧诲嚭鎴愬姛锛屾帹閫佹棩蹇椾俊鎭 + if error['ErrorID'] == 0: + self.loginStatus = False + self.gateway.tdConnected = False - log = VtLogData() - log.gatewayName = self.gatewayName - log.logContent = u'浜ゆ槗鏈嶅姟鍣ㄧ櫥鍑哄畬鎴' - self.gateway.onLog(log) + log = VtLogData() + log.gatewayName = self.gatewayName + log.logContent = u'浜ゆ槗鏈嶅姟鍣ㄧ櫥鍑哄畬鎴' + self.gateway.onLog(log) - # 鍚﹀垯锛屾帹閫侀敊璇俊鎭 - else: - err = VtErrorData() - err.gatewayName = self.gatewayName - err.errorID = error['ErrorID'] - err.errorMsg = error['ErrorMsg'].decode('gbk') - self.gateway.onError(err) + # 鍚﹀垯锛屾帹閫侀敊璇俊鎭 + else: + err = VtErrorData() + err.gatewayName = self.gatewayName + err.errorID = error['ErrorID'] + err.errorMsg = error['ErrorMsg'].decode('gbk') + self.gateway.onError(err) #---------------------------------------------------------------------- def onRspUserPasswordUpdate(self, data, error, id, last): - """""" - pass + """""" + pass #---------------------------------------------------------------------- def onRspOrderInsert(self, data, error, id, last): - """鍙戝崟鍥炴姤锛堟煖鍙帮級""" - if error['ErrorID'] == 0: - return - # 鍚﹀垯锛屾帹閫侀敊璇俊鎭 - else: - err = VtErrorData() - err.gatewayName = self.gatewayName - err.errorID = error['ErrorID'] - err.errorMsg = error['ErrorMsg'].decode('gbk') - self.gateway.onError(err) + """鍙戝崟鍥炴姤锛堟煖鍙帮級""" + if error['ErrorID'] == 0: + return + # 鍚﹀垯锛屾帹閫侀敊璇俊鎭 + else: + err = VtErrorData() + err.gatewayName = self.gatewayName + err.errorID = error['ErrorID'] + err.errorMsg = error['ErrorMsg'].decode('gbk') + self.gateway.onError(err) #---------------------------------------------------------------------- def onRspOrderAction(self, data, error, id, last): - """鎾ゅ崟鍥炴姤锛堟煖鍙帮級""" - if error['ErrorID'] == 0: - return - # 鍚﹀垯锛屾帹閫侀敊璇俊鎭 - else: - err = VtErrorData() - err.gatewayName = self.gatewayName - err.errorID = error['ErrorID'] - err.errorMsg = error['ErrorMsg'].decode('gbk') - self.gateway.onError(err) + """鎾ゅ崟鍥炴姤锛堟煖鍙帮級""" + if error['ErrorID'] == 0: + return + # 鍚﹀垯锛屾帹閫侀敊璇俊鎭 + else: + err = VtErrorData() + err.gatewayName = self.gatewayName + err.errorID = error['ErrorID'] + err.errorMsg = error['ErrorMsg'].decode('gbk') + self.gateway.onError(err) #---------------------------------------------------------------------- def onRspFromBankToFutureByFuture(self, data, error, id, last): - """""" - pass + """""" + pass #---------------------------------------------------------------------- def onRspFromFutureToBankByFuture(self, data, error, id, last): - """""" - pass + """""" + pass #---------------------------------------------------------------------- def onRtnFlowMessageCancel(self, data): - """""" - pass + """""" + pass #---------------------------------------------------------------------- def onRtnTrade(self, data): - """鎴愪氦鍥炴姤""" - # 鍒涘缓鎶ュ崟鏁版嵁瀵硅薄 - trade = VtTradeData() - trade.gatewayName = self.gatewayName + """鎴愪氦鍥炴姤""" + # 鍒涘缓鎶ュ崟鏁版嵁瀵硅薄 + trade = VtTradeData() + trade.gatewayName = self.gatewayName - # 淇濆瓨浠g爜鍜屾姤鍗曞彿 - trade.symbol = data['InstrumentID'] - trade.exchange = exchangeMapReverse[data['ExchangeID']] - trade.vtSymbol = trade.symbol #'.'.join([trade.symbol, trade.exchange]) + # 淇濆瓨浠g爜鍜屾姤鍗曞彿 + trade.symbol = data['InstrumentID'] + trade.exchange = exchangeMapReverse[data['ExchangeID']] + trade.vtSymbol = trade.symbol #'.'.join([trade.symbol, trade.exchange]) - trade.tradeID = data['TradeID'] - trade.vtTradeID = '.'.join([self.gatewayName, trade.tradeID]) + trade.tradeID = data['TradeID'] + trade.vtTradeID = '.'.join([self.gatewayName, trade.tradeID]) - trade.orderID = data['UserOrderLocalID'] - trade.vtOrderID = '.'.join([self.gatewayName, trade.orderID]) + trade.orderID = data['UserOrderLocalID'] + trade.vtOrderID = '.'.join([self.gatewayName, trade.orderID]) - # 鏂瑰悜 - trade.direction = directionMapReverse.get(data['Direction'], '') + # 鏂瑰悜 + trade.direction = directionMapReverse.get(data['Direction'], '') - # 寮骞 - trade.offset = offsetMapReverse.get(data['OffsetFlag'], '') + # 寮骞 + trade.offset = offsetMapReverse.get(data['OffsetFlag'], '') - # 浠锋牸銆佹姤鍗曢噺绛夋暟鍊 - trade.price = data['TradePrice'] - trade.volume = data['TradeVolume'] - trade.tradeTime = data['TradeTime'] + # 浠锋牸銆佹姤鍗曢噺绛夋暟鍊 + trade.price = data['TradePrice'] + trade.volume = data['TradeVolume'] + trade.tradeTime = data['TradeTime'] - # 鎺ㄩ - self.gateway.onTrade(trade) + # 鎺ㄩ + self.gateway.onTrade(trade) #---------------------------------------------------------------------- def onRtnOrder(self, data): - """鎶ュ崟鍥炴姤""" - # 鏇存柊鏈澶ф姤鍗曠紪鍙 - newref = data['UserOrderLocalID'] - if not newref == '': - self.orderRef = max(self.orderRef, int(newref)) + """鎶ュ崟鍥炴姤""" + # 鏇存柊鏈澶ф姤鍗曠紪鍙 + newref = data['UserOrderLocalID'] + if not newref == '': + self.orderRef = max(self.orderRef, int(newref)) - # 鍒涘缓鎶ュ崟鏁版嵁瀵硅薄 - order = VtOrderData() - order.gatewayName = self.gatewayName + # 鍒涘缓鎶ュ崟鏁版嵁瀵硅薄 + order = VtOrderData() + order.gatewayName = self.gatewayName - # 淇濆瓨浠g爜鍜屾姤鍗曞彿 - order.symbol = data['InstrumentID'] - order.exchange = exchangeMapReverse[data['ExchangeID']] - order.vtSymbol = order.symbol #'.'.join([order.symbol, order.exchange]) + # 淇濆瓨浠g爜鍜屾姤鍗曞彿 + order.symbol = data['InstrumentID'] + order.exchange = exchangeMapReverse[data['ExchangeID']] + order.vtSymbol = order.symbol #'.'.join([order.symbol, order.exchange]) - order.orderID = data['UserOrderLocalID'] + order.orderID = data['UserOrderLocalID'] - # 鏂瑰悜 - if data['Direction'] == '0': - order.direction = DIRECTION_LONG - elif data['Direction'] == '1': - order.direction = DIRECTION_SHORT - else: - order.direction = DIRECTION_UNKNOWN + # 鏂瑰悜 + if data['Direction'] == '0': + order.direction = DIRECTION_LONG + elif data['Direction'] == '1': + order.direction = DIRECTION_SHORT + else: + order.direction = DIRECTION_UNKNOWN - # 寮骞 - if data['OffsetFlag'] == '0': - order.offset = OFFSET_OPEN - elif data['OffsetFlag'] == '1': - order.offset = OFFSET_CLOSE - elif data['OffsetFlag'] == '3': - order.offset = OFFSET_CLOSETODAY - else: - order.offset = OFFSET_UNKNOWN + # 寮骞 + if data['OffsetFlag'] == '0': + order.offset = OFFSET_OPEN + elif data['OffsetFlag'] == '1': + order.offset = OFFSET_CLOSE + elif data['OffsetFlag'] == '3': + order.offset = OFFSET_CLOSETODAY + else: + order.offset = OFFSET_UNKNOWN - # 鐘舵 - if data['OrderStatus'] == '0': - order.status = STATUS_ALLTRADED - elif data['OrderStatus'] == '1': - order.status = STATUS_PARTTRADED - elif data['OrderStatus'] == '2': - order.status = STATUS_PARTTRADED_PARTCANCELED - elif data['OrderStatus'] == '3': - order.status = STATUS_NOTTRADED - elif data['OrderStatus'] == '5': - order.status = STATUS_CANCELLED - else: - order.status = STATUS_UNKNOWN + # 鐘舵 + if data['OrderStatus'] == '0': + order.status = STATUS_ALLTRADED + elif data['OrderStatus'] == '1': + order.status = STATUS_PARTTRADED + elif data['OrderStatus'] == '2': + order.status = STATUS_PARTTRADED_PARTCANCELED + elif data['OrderStatus'] == '3': + order.status = STATUS_NOTTRADED + elif data['OrderStatus'] == '5': + order.status = STATUS_CANCELLED + else: + order.status = STATUS_UNKNOWN - # 浠锋牸銆佹姤鍗曢噺绛夋暟鍊 - order.price = data['LimitPrice'] - order.totalVolume = data['Volume'] - order.tradedVolume = data['VolumeTraded'] - order.orderTime = data['InsertTime'] - order.cancelTime = data['CancelTime'] - order.frontID = data['FrontID'] - order.sessionID = data['SessionID'] + # 浠锋牸銆佹姤鍗曢噺绛夋暟鍊 + order.price = data['LimitPrice'] + order.totalVolume = data['Volume'] + order.tradedVolume = data['VolumeTraded'] + order.orderTime = data['InsertTime'] + order.cancelTime = data['CancelTime'] + order.frontID = data['FrontID'] + order.sessionID = data['SessionID'] - # QDP鐨勬姤鍗曞彿涓鑷存х淮鎶ら渶瑕佸熀浜巉rontID, sessionID, orderID涓変釜瀛楁 - # 浣嗗湪鏈帴鍙h璁′腑锛屽凡缁忚冭檻浜哘DP鐨凮rderRef鐨勮嚜澧炴э紝閬垮厤閲嶅 - # 鍞竴鍙兘鍑虹幇OrderRef閲嶅鐨勬儏鍐垫槸澶氬鐧诲綍骞跺湪闈炲父鎺ヨ繎鐨勬椂闂村唴锛堝嚑涔庡悓鏃跺彂鍗曪級 - # 鑰冭檻鍒癡tTrader鐨勫簲鐢ㄥ満鏅紝璁や负浠ヤ笂鎯呭喌涓嶄細鏋勬垚闂 - order.vtOrderID = '.'.join([self.gatewayName, order.orderID]) + # QDP鐨勬姤鍗曞彿涓鑷存х淮鎶ら渶瑕佸熀浜巉rontID, sessionID, orderID涓変釜瀛楁 + # 浣嗗湪鏈帴鍙h璁′腑锛屽凡缁忚冭檻浜哘DP鐨凮rderRef鐨勮嚜澧炴э紝閬垮厤閲嶅 + # 鍞竴鍙兘鍑虹幇OrderRef閲嶅鐨勬儏鍐垫槸澶氬鐧诲綍骞跺湪闈炲父鎺ヨ繎鐨勬椂闂村唴锛堝嚑涔庡悓鏃跺彂鍗曪級 + # 鑰冭檻鍒癡tTrader鐨勫簲鐢ㄥ満鏅紝璁や负浠ヤ笂鎯呭喌涓嶄細鏋勬垚闂 + order.vtOrderID = '.'.join([self.gatewayName, order.orderID]) - # 鎺ㄩ - self.gateway.onOrder(order) + # 鎺ㄩ + self.gateway.onOrder(order) #---------------------------------------------------------------------- def onErrRtnOrderInsert(self, data, error): - """鍙戝崟閿欒鍥炴姤锛堜氦鏄撴墍锛""" - if error['ErrorID'] == 0: - return - else: - err = VtErrorData() - err.gatewayName = self.gatewayName - err.errorID = error['ErrorID'] - err.errorMsg = error['ErrorMsg'].decode('gbk') - self.gateway.onError(err) + """鍙戝崟閿欒鍥炴姤锛堜氦鏄撴墍锛""" + if error['ErrorID'] == 0: + return + else: + err = VtErrorData() + err.gatewayName = self.gatewayName + err.errorID = error['ErrorID'] + err.errorMsg = error['ErrorMsg'].decode('gbk') + self.gateway.onError(err) #---------------------------------------------------------------------- def onErrRtnOrderAction(self, data, error): - """鎾ゅ崟閿欒鍥炴姤锛堜氦鏄撴墍锛""" - if error['ErrorID'] == 0: - return - else: - err = VtErrorData() - err.gatewayName = self.gatewayName - err.errorID = error['ErrorID'] - err.errorMsg = error['ErrorMsg'].decode('gbk') - self.gateway.onError(err) + """鎾ゅ崟閿欒鍥炴姤锛堜氦鏄撴墍锛""" + if error['ErrorID'] == 0: + return + else: + err = VtErrorData() + err.gatewayName = self.gatewayName + err.errorID = error['ErrorID'] + err.errorMsg = error['ErrorMsg'].decode('gbk') + self.gateway.onError(err) #---------------------------------------------------------------------- def onRtnInstrumentStatus(self, data): - """""" - pass + """""" + pass #---------------------------------------------------------------------- def onRtnInvestorAccountDeposit(self, data): - """""" - pass + """""" + pass #---------------------------------------------------------------------- def onRtnMessageNotify(self, data): - """""" - pass + """""" + pass #---------------------------------------------------------------------- def onErrRtnQueryBankBalanceByFuture(self, data, error): - """""" - pass + """""" + pass #---------------------------------------------------------------------- def onErrRtnBankToFutureByFuture(self, data, error): - """""" - pass + """""" + pass #---------------------------------------------------------------------- def onErrRtnFutureToBankByFuture(self, data, error): - """""" - pass + """""" + pass #---------------------------------------------------------------------- def onRtnQueryBankBalanceByFuture(self, data): - """""" - pass + """""" + pass #---------------------------------------------------------------------- def onRtnFromBankToFutureByFuture(self, data): - """""" - pass + """""" + pass #---------------------------------------------------------------------- def onRtnFromFutureToBankByFuture(self, data): - """""" - pass + """""" + pass #---------------------------------------------------------------------- def onRtnSGEDeferRate(self, data): - """""" - pass + """""" + pass #---------------------------------------------------------------------- def onRspQryOrder(self, data, error, id, last): - """""" - pass + """""" + pass #---------------------------------------------------------------------- def onRspQryTrade(self, data, error, id, last): - """""" - pass + """""" + pass #---------------------------------------------------------------------- def onRspQryUserInvestor(self, data, error, id, last): - """鏌ヨ鎶曡祫璐︽埛鍥炴姤""" - # 濡傛灉鏌ヨ鎴愬姛锛屾帹閫佹棩蹇椾俊鎭 - if error['ErrorID'] == 0: - self.investorID = data['InvestorID'] + """鏌ヨ鎶曡祫璐︽埛鍥炴姤""" + # 濡傛灉鏌ヨ鎴愬姛锛屾帹閫佹棩蹇椾俊鎭 + if error['ErrorID'] == 0: + self.investorID = data['InvestorID'] - log = VtLogData() - log.gatewayName = self.gatewayName - log.logContent = u'鎶曡祫鑰呮煡璇㈠畬鎴' - self.gateway.onLog(log) - - # 鏌ヨ鍚堢害浠g爜 - self.reqID += 1 - self.reqQryInstrument({}, self.reqID) - # 鍚﹀垯锛屾帹閫侀敊璇俊鎭 - else: - err = VtErrorData() - err.gatewayName = self.gatewayName - err.errorID = error['ErrorID'] - err.errorMsg = error['ErrorMsg'].decode('gbk') - self.gateway.onError(err) + log = VtLogData() + log.gatewayName = self.gatewayName + log.logContent = u'鎶曡祫鑰呮煡璇㈠畬鎴' + self.gateway.onLog(log) + + # 鏌ヨ鍚堢害浠g爜 + self.reqID += 1 + self.reqQryInstrument({}, self.reqID) + # 鍚﹀垯锛屾帹閫侀敊璇俊鎭 + else: + err = VtErrorData() + err.gatewayName = self.gatewayName + err.errorID = error['ErrorID'] + err.errorMsg = error['ErrorMsg'].decode('gbk') + self.gateway.onError(err) #---------------------------------------------------------------------- def onRspQryInvestorAccount(self, data, error, id, last): - """璧勯噾璐︽埛鏌ヨ鍥炴姤""" - account = VtAccountData() - account.gatewayName = self.gatewayName + """璧勯噾璐︽埛鏌ヨ鍥炴姤""" + account = VtAccountData() + account.gatewayName = self.gatewayName - # 璐︽埛浠g爜 - account.accountID = data['AccountID'] - account.vtAccountID = '.'.join([self.gatewayName, account.accountID]) + # 璐︽埛浠g爜 + account.accountID = data['AccountID'] + account.vtAccountID = '.'.join([self.gatewayName, account.accountID]) - # 鏁板肩浉鍏 - account.preBalance = data['PreBalance'] - account.available = data['Available'] - account.commission = data['Fee'] - account.margin = data['Margin'] - account.closeProfit = data['CloseProfit'] - account.positionProfit = data['PositionProfit'] - account.balance = data['DynamicRights'] + # 鏁板肩浉鍏 + account.preBalance = data['PreBalance'] + account.available = data['Available'] + account.commission = data['Fee'] + account.margin = data['Margin'] + account.closeProfit = data['CloseProfit'] + account.positionProfit = data['PositionProfit'] + account.balance = data['DynamicRights'] - # 鎺ㄩ - self.gateway.onAccount(account) + # 鎺ㄩ + self.gateway.onAccount(account) #---------------------------------------------------------------------- def onRspQryInstrument(self, data, error, id, last): - """鍚堢害鏌ヨ鍥炴姤""" - contract = VtContractData() - contract.gatewayName = self.gatewayName + """鍚堢害鏌ヨ鍥炴姤""" + contract = VtContractData() + contract.gatewayName = self.gatewayName - contract.symbol = data['InstrumentID'] - contract.exchange = exchangeMapReverse[data['ExchangeID']] - contract.vtSymbol = contract.symbol #'.'.join([contract.symbol, contract.exchange]) - contract.name = data['InstrumentName'].decode('GBK') + contract.symbol = data['InstrumentID'] + contract.exchange = exchangeMapReverse[data['ExchangeID']] + contract.vtSymbol = contract.symbol #'.'.join([contract.symbol, contract.exchange]) + contract.name = data['InstrumentName'].decode('GBK') - # 鍚堢害鏁板 - contract.size = data['VolumeMultiple'] - contract.priceTick = data['PriceTick'] - contract.strikePrice = data['StrikePrice'] - contract.underlyingSymbol = data['UnderlyingInstrID'] + # 鍚堢害鏁板 + contract.size = data['VolumeMultiple'] + contract.priceTick = data['PriceTick'] + contract.strikePrice = data['StrikePrice'] + contract.underlyingSymbol = data['UnderlyingInstrID'] - # 鍚堢害绫诲瀷 - contract.productClass = productClassMapReverse.get(data['ProductClass'], - PRODUCT_UNKNOWN) + # 鍚堢害绫诲瀷 + contract.productClass = productClassMapReverse.get(data['ProductClass'], + PRODUCT_UNKNOWN) - # 鏈熸潈绫诲瀷 - if data['OptionsType'] == '1': - contract.optionType = OPTION_CALL - elif data['OptionsType'] == '2': - contract.optionType = OPTION_PUT + # 鏈熸潈绫诲瀷 + if data['OptionsType'] == '1': + contract.optionType = OPTION_CALL + elif data['OptionsType'] == '2': + contract.optionType = OPTION_PUT - # 鎺ㄩ - self.gateway.onContract(contract) + # 鎺ㄩ + self.gateway.onContract(contract) - if last: - log = VtLogData() - log.gatewayName = self.gatewayName - log.logContent = u'浜ゆ槗鍚堢害淇℃伅鑾峰彇瀹屾垚' - self.gateway.onLog(log) + if last: + log = VtLogData() + log.gatewayName = self.gatewayName + log.logContent = u'浜ゆ槗鍚堢害淇℃伅鑾峰彇瀹屾垚' + self.gateway.onLog(log) #---------------------------------------------------------------------- def onRspQryExchange(self, data, error, id, last): - """""" - pass + """""" + pass #---------------------------------------------------------------------- def onRspQryInvestorPosition(self, data, error, id, last): - """鎸佷粨鏌ヨ鍥炴姤""" - pos = VtPositionData() - pos.gatewayName = self.gatewayName - - pos.symbol = data['InstrumentID'] - pos.vtSymbol = pos.symbol - pos.direction = directionMapReverse.get(data['Direction'], DIRECTION_UNKNOWN) - pos.vtPositionName = '.'.join([pos.vtSymbol, pos.direction]) - - pos.position = data['Position'] - pos.ydPosition = data['YdPosition'] - pos.frozen = data['FrozenClosing'] - if pos.position: - pos.price = data['PositionCost'] / pos.position - - self.gateway.onPosition(pos) + """鎸佷粨鏌ヨ鍥炴姤""" + pos = VtPositionData() + pos.gatewayName = self.gatewayName + + pos.symbol = data['InstrumentID'] + pos.vtSymbol = pos.symbol + pos.direction = directionMapReverse.get(data['Direction'], DIRECTION_UNKNOWN) + pos.vtPositionName = '.'.join([pos.vtSymbol, pos.direction]) + + pos.position = data['Position'] + pos.ydPosition = data['YdPosition'] + pos.frozen = data['FrozenClosing'] + if pos.position: + pos.price = data['PositionCost'] / pos.position + + self.gateway.onPosition(pos) #---------------------------------------------------------------------- def onRspSubscribeTopic(self, data, error, id, last): - """""" - pass + """""" + pass #---------------------------------------------------------------------- def onRspQryTopic(self, data, error, id, last): - """""" - pass + """""" + pass #---------------------------------------------------------------------- def onRspQryInvestorFee(self, data, error, id, last): - """""" - pass + """""" + pass #---------------------------------------------------------------------- def onRspQryInvestorMargin(self, data, error, id, last): - """""" - pass + """""" + pass #---------------------------------------------------------------------- def onRspQryExchangeDiffTime(self, data, error, id, last): - """""" - pass + """""" + pass #---------------------------------------------------------------------- def onRspQryContractBank(self, data, error, id, last): - """""" - pass + """""" + pass #---------------------------------------------------------------------- def onRspQueryBankAccountMoneyByFuture(self, data, error, id, last): - """""" - pass + """""" + pass #---------------------------------------------------------------------- def onRspQryTransferSerial(self, data, error, id, last): - """""" - pass + """""" + pass #---------------------------------------------------------------------- def onRspQrySGEDeferRate(self, data, error, id, last): - """""" - pass + """""" + pass #---------------------------------------------------------------------- def onRspQryMarketData(self, data, error, id, last): - """""" - pass + """""" + pass diff --git a/vn.trader/qdpGateway/vnqdpmd.pyd b/vn.trader/qdpGateway/vnqdpmd.pyd index 4f966e707225943efd28dabd7774b74977364d96..e403a3a4b1e6f5a2ddc4878934693b9d15d45a01 100644 GIT binary patch delta 9952 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 delta 10063 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 P*;5;BYhEcj?iKzIt%njm delta 27795 zcmeIakAGZcl|Mc+x%YMgQ#z&7c1ovoN~aKLN@p^^lSwkAK?WLNDp7+(m`Ze`1eju6 z;}V>(WOuU?FA*%~UuM%UOnIYmI`ik3O%EBN_P4K?mRapH zzhb&CBb_$gZG>LtGru<7WrX5ye`C7$0%IZb(Lb7=+i2{_Txu@cZZfW9-gjQv7taI# zUu|VC+-~fqFL#z5H>RoOvt@S~vzZ@%w(MU`#(d_hU1c3*CUbSh-d)yfymWL%w4UH! zzd!#$>2I(uyCv0I6-$#3PIx%JuxX% z8|{>z6fQBwsqDCLnQ@MG9~br-Lv+h=A#7}=M~({zjs5f=$A#U-dD`%d@NuJ+{^}XQ zZET@$KLg2Ldifcl(Kt>OCtzin4xA8fHah5u6T&WIl77t85beqeA41)IS>ZNgBfXLp z{KgU5a8kGeHtS9bK9l)hspBL%6QS>(M7v4)-AUnU<1p=gR;Wjx?nYs<{G7&~73z#p z`opt=*VsWjpA%|e=eFk{Gf!XP!b-p5qJg&OP;}C5T#V9Ja!|a?wpc;bNTDy&zm^T%@`egb1wM`-1Qp?2A9WAbi@0 zDgDF`g?~m*cm7Ct84L2xkAx>pMtkPT7lq?Slz03@xJfX!(TSIY$Bl!TkIV`?O-6U- z{(lv|U1prh?D>VTy9|5j=2tK?u=2%U3a?_5-1jRXQ)cYU_OXrsXquenJ|Q1e-xfGCNsbLqwqtM(VF?*>%z@tMklR(L-?^Vo%y#n zgugRk@(!&EUotu~XIF*$jK;CdXWtfX!ak=L-w{q5XP)}5xPv$KDWmwR$(W!Mg7~_z zKl79*t~FtcJhw)?4D#4-A|6u{Vxa`$Y&OJV$(F6#Y$|NzcGtd*fbMn zaj$Wb7P(j?dpQal#kh!4XE`L>=?SI=>1SNzNIVb4GWof1(8tb$l^6}42gwfl0W;I| zIv3Nl>wIyKu|PMS4=OMWVAU%!3WVX@jT4;2V_X60-)9qZu=-~^*Am;eT7l`$1oSQK8Uwum%x@(^?Hj*AN7susdg?-Pm$8{%Mg>~ix&Z||mx~d4 zj0-!x%tbG4wV^1`EnKwGV<^_lIbmtt6Lji?V58SZCtF=(_}j&TvA(_D1W`dui}w2zBvI?P3Zj&k9mQ@h|FaWY>j zM$oORFU2Ow(&0-{w?s#|u+u3n8pwDViX?fs7@|X5Owkc8R_Nqq*iKIR(`D##6K$;k zvzrcZk*9l6m@GaTt-x4A^l}9@Kr1;e7k%i=!OJ02p!>OS(J?OKbefAUT7LzK5!%Pa zEFHc=yxe36(9ji7tfW)SZ6@Px6g}kOVvG)PF;7QOn9MN4Z#~Q(RP#@k$g;FNMtNiW?IKnqLsSOEU&poIWDqM0g#Vh#G-78EbRARi2(ms$F85Rw&iHYmn1YmFfo zYodEYV0P2DLtt8Im6>+h9TuCh-Fw2=^`rD{re;Z~7H6UNZ`I;iEZxs)(E1#mtr0IX znQtUl1Zy`&EfMV5WqLS*35?Ox5!iOn@44{N)><&e4UM6qdf4*05pSQsb>aUs*xPhPlHvw*7j1A-)LhO*hpc+BDPm>ad;Ml&=#%%m-dQqTCXt>JftaX{;Wr&`U4XV;Y=P7R3U0 zkS8kEVv6pLLS&NCQEbBm{WuDdJ~|u4TCPyTK6%-C_F?huG`|m1>!uA?L8O!RUnPg< zzN^F=O@%MyPT>G;-9wAFJ3;kL`y{j28A|X@<$sAaB){286dfjdHOI&4uMUHY;W7(bb`>Ua6qn+;){||QCAKxclYh1`gt`Xlf!glal@eDGoE3Xs3 zU_$7fY{Y(Rq(Y;3J65{odRXnEVJ=o^>3TV!Ms9#{D|OufYJ{e5;IpTNR&T%w(42AK zhzY}1>4;+*XX$7hgG3~W<1B+$#u2+?bj?BZXPQz65eRMc?St4xPI~De4vSg3;{9-! z5Pj_ZVg=^*q4&$a{q*}0IY+7ReoTKWZM_LL=jgyq2y$uayGfp+r*DFlMf%N6Xdyv+ zo8-kvG{NRFWt!k-l~n!#%zJ+(`T;R3r55jy3e zN-_w5m3t&Z9`JtvS-=Ef2=EY~18^%K2DlP%A>i%9lHtDqzXbT8e-$7O`0%Hsl;IvA zp9ee&r~vTKU{W%40-6CKfE~a;vAZS1G~oMy5x@}OA;8}PIsqRCybX9i;F1nB4ln@D zz-}J!Bftot8ugVdb9YKITm-}f_~l)aAqSWMd<*b-z$XE5Ko!6S5CAK8N`{{T(tt++ z9e`Fq3{U~6M1vu~b%5W(?w9{c>HM=8{V3p3Kri4Pz^y6#iUFzsHh=&)gV8PkehSC} z9)f{Rz$XD8gwb}u=Kv1@(tvTm^MFNw@M+iqR05)a7QkNu`T<`Dd>`;5z&zl;0I9d} z%lem+;bK4~AOg4n&>XZx)fE!Q;Xzs-N-v#8a0fT^V0iFT;6p#lL0Ox%c>jbC*Tm^^&J`U&v`~zSN zkORyDehYXTZ~*>u~#a~>DH-cv7nE*Efy3?YeyH8}6 zp;%`DZUfAtZXR{ZY0+xxDYLRn=(uF<1$5K4gt!&aBaC8O^LIsS(r&PhZ82E0fHZIe z<0u>Ga001vh+a&{lfxH4Tr@>z@>Z*G_+@ z)UOE*KCHp}fhR7(+yJ^Xc$)@qqEFv}PDJVG9pW{qO4N+)F<9*=e~Y2;s0HBhD-G7= zCq?U*RbKLIu>80n*XMw{fX|_Ht32PZXmtROp~-mFEKfV|2obvK4hTFnlNUda&>_>Ly46{{VO`DAOu027C{AK9pymb3O1A zDHw2qkyucAY5{&VDhl7i2vyz!a1(elD1QmX?*Q+E-Xv&ed6{(tWjA;{(gEOq3z=P@ zFNI7u=w-;XqwE6BGR?qGq5fjf;-?_oOUApz%{UKHY{#{2$6fHY9My7Rqnq!-kv%|< z+$DZ-%g7TLPXr6lS!V4IVy<4sJOH1h+PlTgTV~Yi{9i)kcBOh5_yXO@)djUW`{|PQ z3~&oQ&ehJZE5?%@W!7X!(H;Yy&b)ZHc!v=wW%w|1C?9?4FnScDpK;Mb>+gYXQq_%r z6nYHkSQ2Fq?Yl<|ZW&ao-G|Do%K@c23Vbwk)U-S*ihZnz*9On%{)}UW$M;B3cc54c6%P zGHV=QQ)vTmE1*K9$1X#n27vbi+KL8%#{peMec)C=e^Gx6^Z~;vodn(um{4gq@MsFZrd7tW z9h(nyUZuxCX8|ik1HiihW-J*mkrTKZ;85xOW{e)-R_P@0Zou3(MCw6IlB4t;?|8*2vm8*4VKNSk#L-_oih}DP#l-$QE%8wzibmP zAxEFsfQ0!_AGVc=9_bS+=&3$&|3={`WYixcN*ibgt^ERyFl`k}O#F>xZPbXDf!6}M z9bkJ_v`)}Rpyt<#uv#zFhBRsdc%z`R=cpcoD(;=9z94Scv8U zl2PWh^-9(yjR|gO6|@;ARwKOuGhuBttHl3avW8I2IRCIp40ID8a?dJ!mNC+LbkMIA zW$~HMOV%D$ojc5PH~@MCQ289D9?(Hw`l7h~U{Q=yAO6v*Djb8M8RnLt$~3PcCs(VW z?Kob~F?m9?HdA@Oxc%~?c+srZL3BN_KO>~Bw-00`G?2a4Z4r5(|xdpi`?V= z;#N<`4@*)k+W4SkozrM?-xfg^-qrpcw8L5vR_lXW1)@LW{KIM?&@q7AsA{s0Uh5Y( z->enoz72f8q{@>!s-d|)t)W30nje>}vzTzki$B&cOE`y)9T7LwuIQ?!z9LzL+_~Z- zX~}BS@p_L+Ru>un0VaI9D#O>Xvvs@)@S1eIkzvW&N(b3Qhpwvo>)1g$UfVY$>wu0I z9g(cVbd*hu>#CN&DOqzmUi@2_3mwn-ZJvwQ*u;vi%J3xS;s@u>h5I|03mq>Ho{RQ9 z%yXfu%8p?!biCzbmr|iWu~ zg6E@CY@$I|C43)Kr{gt%*Q(?7g4aPi9^tvrRoOF`3mq>3-ms202HrRwW)nGGRpkWc zLdRuj=Fvemp|4s*FLHXb8s58R2`fiO*~F|)JjzwN78lXtf=*86(Q9l% zm{K-)41?qo#XX2cRe6=_z_q;MT*y4yHwY6hRlHc0M=y%JVy6o*>r>^5Q!Ml72%FGX zjX=CXXI9HA_BQs9*gtfdO*HAmQG*K; zrN*2ZJfgvyfj6o-afgQAFXJg?q@$XODGk1$!43ahYRsX*LmIpZc(Jjh2JZtt0%*#r zmm6et9h?rQ@QY*1dsQ+&2c;yG7|(0)RSjvqreZ~dTPI76Rci2<25;5i-5PvIgHLGiSq;8C ziS@UiRHoN*9BYKBPGht5q09lA)#a%`-Ktub*VQ$kE&<5GP7LeX3XpG5yuPab|5R^C zVO_hRJP4ToUkvOl}eHCsui^U>v)JCrq@_*oYsCFIHjuagZjiobX7`-a@7kDw5HP=QYiu?*iA6Ecea z9AgkDf$P-oP@r zyA|h(<=!RHFXK1mer-ch-h)cMO|6k1-^vF-@(oIqN%Ze9%Z}3*ST@J9NK7R~mhU%w ze-RW}>_Z5dgeiLao8m>~9Y`4Y0a5M53WWKlVpfE0bnsg+?4mnSNIoRmBZG9oL*k}w zeAyU43MX%P{E7njIur-s`pa5P^a_e{PCxn1pmv9^6MQF7MuNTI`8H&G=z1$XwW1A^H6g2&yMXeI zK$+EYA4t9osFRGn^(2fo(S0byR#Yy?Y7$R(c0is&G;!sQl(j+>tiaNDhjk~1bCD6Y7Fou8&PSXa))O$G#kxo^vgldYxLQkFs^i{H~^PI zrwrTyK6RoR0XER2(p=95x-|7Xf+0;kk1(s!KxLbTr_S9oD;jwo(7a6Z{Nsn0z^qZ= zMr|6Jd+pHBTwkfu#R2$qbWA7TqM^A1txT)!%YNLY5#Sja(9qn05e?0aPH1SB&+6z| z9lfZbdBCfnY5FPAzLBk2HGhBN*6j4gQ#c>E%B`yk>FAh-X2Z=In)O>XG}pIlXl|-g zLvwv^i8dNCUEddd55j9br}w9}`8fmGTE9fo5J1 zMY{92c>DRQr$jlUxBXP46BkKasN0G9!g0~Dt>UN1v7lf4`OHp(Y?FK3LY`;v`J!Gf zwo}(Lq6L|mjE_8nk6Rk({uAJ@JR{nW3CeiI3GlmRd~N@al-{wWQD*JNXE9}|=@X(u zu+56rBRg!5o)pWeJS(0rL=^`0+of{yXGO0tpmMsiqD{!EL}DANpF%Zqf}r3p_o92oXE9067fX{=$t---L$0BwXVLKi1@C2iO2KjYvf&dWr&!cYN1sC* zuIIpNRq$rU2Nk@JakTfG+}`0FPY1JnB;yr1;B5-t!uSy5UVM&SuEyQPW)x`O51>|H zJfz^2KLFm&xR?J^fU9w*u<>VF7@uMsdF}JSR~g6JKM&EQ!fJgUtYHNoWPDD+rx~}< zu@|sEmQRYJWSL$~Dbi)tD z?;4|-^*<8dF>*PL5BcIlvxi<3_m<(4=SOBl5}N;AUSq-ok0sN1O6)M=U*=B!RLq!! zk>ANxnf{-NQIlX;Dhblc&&8ausO8Mhi39jYtHb{$p1}W3WjyoZ&rL$;Pl^TSuS9DZ z*3|QBk?@IT6gx9ZzZNG=!rU8*ME2js5u-48R?|k`e~4W|XjQeaC>D%D>}`c||EJi7 zTZKX5?Mbk{mX0rp_X=%BnUjgXDo#PVOsVIgQREL|yD+D4GTA?fW}{FL)cO~o|LU^% zvQQ8ePX0A6Y=e2Ain$+=Ak{EY(#|JeTni#`B6sR-<8|BX5Y?AAJM0AsMAg#*rq2 zP0ft=%lO*vjiq)bnY9}qrhxR3A&>O28Tu zj4#XhM#E-Bg9Ex_9rAsY5ju2M+)UQ92r+T0J&P2-N39y>s{OkrK=Prvh+7#7!;>F0 z$uq)MmQ+y-c~)U1&sOjse5@ydO>Qf9BeLGnN&sR6)R(_u(C|Auoc&O z#R~p6=Pg)i2C22O`NN78KJ)ri(Qy{tOxQ(M8sZ6RW3$hBY#4%PW z=v9&>l}d-wN)t-T^GfV6L!}MmIUPG(QW;WJa;ze+#1U4R)2rN5Qn74PTJfP&#$qgo zN(|&Vt$eDa(xs{l%PKsU!>lr)SLrCJEU7BCi;H79%_hOsgs@tRk<=Nmem$*R}GQl1c=1+)67-#X~&jL#0!%(pgd&RaItX6<(L4 ztg@(A`D{tW;Z#~_K&gyny#*@GAkP{8UzJq)RF!d7k;igBt4!%t?k%aTsw%D>#j(7` zDj|^Pw9-{lX-6Foe?V5@u^d_pl@YzleI=E7RYka@IF?gT*=7fMPAi{NR5+z6|rwF%c4l*U)(D3KX&YMU{q!YMu?0X_}YGV zX#%h&4$K}hZkFm}DP-J?PcV**n>FH|k_NnyHQpqS>)`;RNe`h@?mgzDktgw?bwDhbbLGJ2X`eWS}bfwi?}NRU)%31 zwTO-Aly;xj>r-?`d>l|N;wO>{xZO9Mu&}IXx&0+A%n`JBj@Wi&2W(@G7;j@7bHwc| zYc$|^JD^ceq?T9;apMwbAdJd!1NhppK&cJHjZ2_`xWQ6GEQPqi_!Q%K;MfU`WU!=x z2acW4z`x?7h8lN5sz<>)cfva+6nvEV3kp8Rd^;U>LEhp5AD;qaJj8fX#@8-~N-f|8 z!-W>66sbv;T2b&t#+|fd7mp%b(t!8wf(E=7HPpUKn&5F?%2L%ODTK{SA%!8MhK4SM zEsXn8X)DbHBn!=4D!J^l)spN->*hT zR3h)f{(kjx=@y}*P6<$N!UaBY1>7X7Fi3e6yF&5`wt7Wmw=^!~6`b&44>Qf~mWG8y z^j-UA^Ez~IN@dKfLmS5{r3W~I?7>1HYV5&~`u1Q*c3 zSHdYPiyU^!4=^X8a=NdSY{Gy_;Mqi=F^--1pR6mTo#nHr;Kj<)t5-@7^Bdw`>9X?4 z{R%fn$M#Bl5%5m$MMo@j(2c(N+z8!K#^rs(tRZG$-!MMM_=1eD&F?R*CAO#s8rYT| zNVR*g)37%gA7mUS3-Go1Yf2hO6+F^T!TCOAu<~@;s-zAfsdCa)Ql&7i67pQUT7`q6 zpmMO9X7gqYuK5~`g+{NG9OUs!`!_a$ENZu^Re0<0W5gqVsE%stC)N6CIt^93a9v5& z2Amsqp_DKC>#i+LQ45&zvBq1i3mz-@sXR8j>QGR&dzSM^Mtt z0m)8dVX54va=E7H>J4-}Bzf&Ks4Dg)51jk5%*xpU`m!yI)29O88o{kZ!&0NA0|c9y zK&dp44oT*XttwmFLKD3h#!kqq>hj(wua?f|L%SNm&COv9E?14?s-5numUfr--=OrM zi;h)e^=3g9JGY=#;j2=r5yG4WQPeI%<&8=w@m^j|*Vmxi%_=8ZgPH1433>k_8rp<0 zl`~T#IfMn3;N2?n-;xmRBGT>X77DyTN8nCKnj+}wyuz~7Vx8>=l}43wxt33Al_PI^ z{-f1^%IL0@T7+qph`)hOz6E*Cf9o(6iCRez`EOdyOyl&blNvbht&?67`fpMi;V_l? zn|i6tB#eJRW@Xa*&@W-~gPNhgauue0QROUiAlkAYr?`s_?}y!{{ZL3SzMJ3UnT0Up z;3JLk!hS?NJjyo!uWSI0ZP=h}LuU0gKoq$Y<5LaTlCuhKxf*;sy>_*<^-+#(v8$ol zRHQ|^?`n*+w@3>#!u8`aP3amuyT5WZw)`S9b_&rCE2H6+%J|+Vwc}--j$VUaAc?pJ zEiYYzNQJKrV%#1BjuSP8sAavSq*WCxl@nFS03i4s3;;e&6wxg=Lez{Z7F|L)0~mi#(W4OE(T^%_Jc)ia0YZRt=WJIT;lWOS zAD8Mc@!{mM16Co`@^RdM07YpRaP!CMKjYFzx6PuSM?DVNK|t}uQ~LOcgVOC+B*5lZ zg)yiN06GExgUK@orJwG~L!QT!#88_6A;5nh{;Tho9z)>z`x?-32@Pn38w_#%{1 z$n|P?|CE#r1K_oMQX_}&Gif_49@(++|9#WU|NEwy|9^hd%=ZlY@A=rF%r8GAU16{?DH~^K?iP2#-R5q0C*2+HRky)o_1HWPkI&QKiFukmEuMs@)zj|j@eFtdJtLk` z&zNW2GvUd4<~)m@CC{qIP$g8Et1MNvs>-TJRkSKz)l}77m8j~h>aFUl8mdZHjZ|f; zW~yeZ7OEDj3RSCB2Cv!c^tw}CpSQsq^EP^$yzSmDZ@0JKJK!Dk4tdkw5pUKzh%Jx9D5) zE&B>StKaE&`F;M7KjM%2WB!Cc>F@UU`_ukm|F}Oj;h*wP`{(_6|FVC@F9gg1d%zK> z47dZ)KtrG@&>UzBv$k3WY+kP-Cbi zln5n59ig63Z)h+y6dDbUg|eYsXf`w#S`00PRzrrcHEavJ!WH3AI1+9Q$HR$mYq%ra z8SV}Dg@?lF@K|^}oC{Bd=fd;hrSNjtP%Tv3s_oSk)s@we>S%Smx~aOgx~;mix~sac zy1zPIJzSj{ub!x$s-CW%ug+I5SFcnHHRc+7jiaWr#$6MwX{c$cX|8FjX|L(3>8|Oo z8K@bq8L645nXH+vnW@RwEYz&j6l%;7OT-azM%)o!q#+WEG)Gz@?U7`pJJJ&whzv$X zBBPPXNH#JPnT;$&79)koYQ$1&t##JAQnkL?P;IQXv9_f)QJbvosO_oktsSf#svWHz ztIgKtYG-TbY8PvlYFBFwb=EptovW^*E>st(YpjdcCF)x1I_f&>dh7b?hU(IFV|C+o zxw@&kxw`qfrMl%hL%mRMtGCxz)K}I=>ZA4X`lkBU`nLMc`mXxE`u_TKeQLOVyndp7 zs(!kDzCK^ST)$FZs9&u&jN#mYX9#Yy+v>Kt9d4()!d>b1xkK)#yTRS)j=P)THLdU( z_L(ksx4YNf=N@nmy3_7q_o#c!J>i~o=iF278TYJv-koE$(SjU9Jr-*Wu~(bi?ubJpFLJA9SMRm)W??|Q7oYxUZ^cCQ1z>+)85-EiNKH{y-TE*ysw zH+x&W32!T$IqB{2cFHc@>+L(otw+6M-f`~)+&h=@PRTw#@6F48zT{o@uE^eA^mQA& z-QjcjDtwjjdY>;Odw$HeTWTJo(RNErNPzr}C!JLF(dsRKE zUVoo|z(438LLeFOkNU^_6aK6}Cr6W6|C}6A7X3?dR9W>K5Lc{nWN`*65L-fl2;xgD z(3lFu5n@^btq3y7K&KpNdINn3HG_dP!p&%4Tn;vifu(>DG$YKof{|cU4l*6V&R{=6 z%xG{dI2D|hgNq>~gd7Mhp-?2$6l#`ZN?)iyG=hkd3r&Ucp#?dX*u##n50NAl4>yI| z!$~=a42MU;S%i@Ja6ViJuZB5zxT}5DjR+lW)$P?i)xC1in5@oL&mm&0R2QnPH8wd` z#A+IAS`jI_YkF#iYSMCyn5~(sSw@7gM68jDNTnPb5|P$O7b3%8WGFHonMlb&VJWg4 zG1ppZU9}ap(b@(%7IfBj)eayMjMa|UPS?)JF+iv@*EtaZB6ZQa=DHTy_xtMx>PF%D zQ+3mI3w4XK&pYa!^&xnCQ+;!Nvc5z1^^y9~`WzfRU%$W(j`uIo&~D_Q~}RvfXBd3QnG^#;=E&rn1L58zzZ0pBP z9+OYDJkB(OpU*TmPP4e?G#kVAn~{$(1Gbt|KEUFE1a=i4UFpDBAS)kQ%K<~sDj!$T zU_6*g$R|~QFpW*bXH-7895l$MlRFd*#pPqE8yhGsA4oIUK+Ez`)9UR(I2rR!dgl={mJluMhz|{NL})=YX!mvc z2I2WR`1-7G9)7+A7q?^1DllsyISXi#9l6J!VlN&-Dlmr0oAWOq1F*{e*&w@Qr|gEK zaKTxe_Xaqi4X1nrr+gdctt&Vb9LBuO1n1yS@3sdS0KA@U-Qxfp<^7t9)W^po*3(U~jGtyDAydzao|5+)9 z#|G&lak^%<2IdRW9&sFJIsQUfkamdeIIr>5@+)Zcs|BfF(XljA*NK)K$=HD^gN0;7c3n)m7;-alk#~9-$+zOWW~>q3~PM9ik0~QUzUp2G36u zwDwJjzbX9#Z%RQFwQoz?#SX;QUVJu7+ATIALu;cWZ%e6i?!jPqGMuBsXQiF^b589$ z(uY#BHS;x#NNa3JXrhq>l9@gPtcget>C1A&TI;BdAZKaA=m%=k$Wo?}pA>5Ch)fO0 zN|JS5$VNsGk!I^w5Rc4=M(+AXM57ku9?AON`avWelZZw$^>au$;2gN9vvU{_h+OW< zl$>QWBe&?0bBeSai)Q5fVbyI$?ofe*p$U08Rul;Wrv@XQoSY7@GZ~Ns*x^nQ9Q=Ij zC*?ex&-iiKt@3gX&J*Us2_EvYQ?HWcBoPLK%A2!k|kh6Qq2cn4Ch?}E75~9j!(FWz!cKx zB_z`9T%1HV2Afj6KJc$zWY6QsopZ8>EhBR_BWJD*`QT$QM5eY-XJ`P)@-Sl4L}*4% zm4&bcX|fY(GDoL&B*3yrGWin$GO&k9JdKMZd+})oZ*hwP9nRVL3X>0y<^7SsjTziT#MBuQgv-eY6q~1 zhH)XgBFU91!8El6gaNM@t;F&u0iNMd`C#17Vv$rF!5O=aI#`e@E#Ok*LXzXdg(!g(r$dguBiIEq*a!KVB_udDT!38I z32|I~y08aEB4Y@X$_^;Si)3vl?l;4@+l(V>Pxj zy=I>cS$7nfNINoY&Z;MnMb9E_HsD09^f$uiJCP7;*6%%*Zvok>72X|@UAq@~>ku4! z3fJLfT!$T@3OIC=dT5TOLep5c0@lriEF&Infe#PL{;RB*Q0;*KR$$ed;Jw|r%#Pv~ zo5wO)ad!>Xv|y2vxUHsfOP$62l$XbeKpu-U!A1Z3^4R$%3Ky-!Wi(bBuie~Q%O_hG zJe6;w{ql-U)Xvl61!?m|&G5}`Tsiye2H~H)PV-1Sm+A_2G%c>V)W+VJLz2nfh(t4r zFEuvNf2~TFl=Zqt`N-OFWgL#yCEw=8JTpii7jSR0!oNZY*sbp_%?wh;6)X)o&PetH zU24|D*QO~s^I7&F_2*1iA{LTdC1FKjbOVA#S(7H8i_M|K!8}1NMtVtZJl0YicixhBBP6B6<0&+T2 z35SZ}4WdVOs0oDDMTAx>7KO8z1g;Bx)q_};T=kNizqsTKCXR*aD&;Qlo<&4b_MQs( zP6Frb0AC8G;W`Ff2y9rBko+((ghiODov&Ru=cw(JFaE>umuy`g5z>mwz8fCH2W>Ar zhL72)`b8YFScy2EoN>rHaf6S^_ji8t;;7go-`K~I?{iFCc86Ep4ji#D9I>4^TGR5K zo1eR;mlraE1`xi(2tk)Pc96G_G;ecp;jHOPG;=J8*$(!1O0WUGfPxiW6>5p8926 z;2iJ_UVvsSK)am6OyK4=jYM(<5zR$kJS$zxiQ9##F$Af3993paun+q`fg`F9?=cgY z;nj#B&#?o0e*__E79q)uY|Et_Lv`&OjO4jpz++0GPKibhh(<}AJwu2_Q}wevvk82c zIiiu^w&1*R