def test_TraderChannelStartupStressTest(): ''' TraderChannel的启动压力测试 1.测试反复重新创建TraderChannel对象是否能正常运行 2.反复创建TraderChannel对象是否能够正常回收进程 ''' pidList = [] # 启动调用测试 for i in range(10): traderChannel = TraderChannel(frontAddress, brokerID, userID, password) data = CThostFtdcQryTradingAccountField() result = traderChannel.QryTradingAccount(data) assert result[0] == 0 pid = traderChannel.traderProcess.pid assert pid and pid != 0 pidList.append(pid) # 进程清理测试 traderChannel = None process = psutil.Process() sleep(1) for pid in pidList: assert pid not in [child.pid for child in process.children()]
def test_QueryApiDelayMechanismBasicTest(): ''' 测试query api的延迟机制 ''' queryInterval = 1.1 traderChannel = TraderChannel(frontAddress, brokerID, userID, password, queryInterval=queryInterval) data = CThostFtdcQryTradingAccountField() # 第1次调用api result = traderChannel.QryTradingAccount(data) assert result[0] == 0, u'调用api返回错误(result[0]=%d,result[1]=%s)' % ( result[0], result[1]) # 第2次调用api queryWaitTime = traderChannel.getQueryWaitTime() print 'queryWaitTime=', queryWaitTime beginTime = datetime.now() result = traderChannel.QryTradingAccount(data) endTime = datetime.now() executeTime = (endTime - beginTime).total_seconds() print 'executeTime=', executeTime assert executeTime > queryWaitTime #assert executeTime - queryWaitTime < .1 # 确定第2次调用进行了延迟操作 #assert executeTime > (queryInterval * 0.9) ,u'延迟调用没有生效' # 检查返回是否成功 assert result[0] == 0, u'调用api返回错误(result[0]=%d,result[1]=%s)' % ( result[0], result[1])
def test_SettlementInfoConfirm(): ''' 测试结算确认 ''' traderChannel = TraderChannel(frontAddress, brokerID, userID, password) requestData = CThostFtdcSettlementInfoConfirmField() requestData.BrokerID = brokerID requestData.InvestorID = userID requestData.ConfirmDate = '' requestData.ConfirmTime = '' result = traderChannel.SettlementInfoConfirm(requestData) assert result[0] == 0 responseData = result[2][0] assert responseData.BrokerID == brokerID assert responseData.InvestorID == userID
def test_OutputFileDirectoryIsolation(): ''' 测试通道目录的隔离 ''' # 测试交易通道 with TraderChannel(frontAddress, brokerID, userID, password) as traderChannel: assert traderChannel assert os.path.exists(traderChannel.workdir) filenameList = os.listdir(traderChannel.workdir) print filenameList assert 'QueryRsp.con' in filenameList assert 'DialogRsp.con' in filenameList assert 'TradingDay.con' in filenameList assert 'Private.con' in filenameList assert 'Public.con' in filenameList assert 'trader.log' in filenameList # 测试行情通道 instrumentID = datetime.strftime(datetime.now() + relativedelta(months=1), "IF%y%m") with MdChannel(mdFrontAddress, brokerID, userID, password, [instrumentID]) as mdChannel: assert mdChannel assert os.path.exists(mdChannel.workdir) filenameList = os.listdir(mdChannel.workdir) print filenameList assert 'QueryRsp.con' in filenameList assert 'DialogRsp.con' in filenameList assert 'TradingDay.con' in filenameList assert 'md.log' in filenameList
def test_OrderInsert_WithInvalidValue(): ''' 测试报单 ''' traderChannel = TraderChannel(frontAddress, brokerID, userID, password, timeout=1) print u'日志文件输出到:%s/trader.log' % traderChannel.workdir # 尝试提交订单 requestData = getDefaultInputOrderField_buyOpen() requestData.VolumeTotalOriginal = 0 # 手数=0 使表单无效 result = traderChannel.OrderInsert(requestData) print result assert result[0] == 15 assert result[1] == u'CTP:报单字段有误'
def test_SystemHighLoadWithoutTraderQueryIntervalOption(): ''' 测试在系统高负荷情况下不使用转换器的流量控制选项,可能间歇性的出现错误 ''' traderChannel = TraderChannel(frontAddress, brokerID, userID, password, timeout=10) data = CThostFtdcQryTradingAccountField() # 模拟系统过载的情况 commandLine = shlex.split('stress --cpu 3 --io 3 --vm 10 --timeout 10') subprocess.Popen(commandLine, stdout=open('/dev/null')) # 连续调用10次查询api for i in range(10): result = traderChannel.QryTradingAccount(data) if result[0] != 0: print result[1] assert result[0] == 0
def test_TraderChannelPoolForFaster(): ''' 测试使用TraderChannelPool为查询api加速 ''' queryInterval = 1.1 # 使用TraderChannel traderChannel = TraderChannel(frontAddress, brokerID, userID, password, queryInterval=queryInterval) data = CThostFtdcQryTradingAccountField() beginTime = datetime.now() for i in range(5): result = traderChannel.QryTradingAccount(data) assert result[0] == 0 endTime = datetime.now() executeTime = (endTime - beginTime).total_seconds() print 'TraderChannel:executeTime=', executeTime assert executeTime > 5 # 使用TraderChannelPool traderChannelPool = TraderChannelPool(frontAddress, brokerID, userID, password, nChannel=5, queryInterval=queryInterval) data = CThostFtdcQryTradingAccountField() beginTime = datetime.now() for i in range(5): result = traderChannelPool.QryTradingAccount(data) assert result[0] == 0 endTime = datetime.now() executeTime = (endTime - beginTime).total_seconds() print 'TraderChannelPool:executeTime=', executeTime assert executeTime < 1.5
def test_QueryApiDelayMechanismCounterExample(): ''' 延迟机制的反向测试用例 ''' traderChannel = TraderChannel(frontAddress, brokerID, userID, password, queryInterval=0) data = CThostFtdcQryTradingAccountField() sleep(1) # 第1次调用api result = traderChannel.QryTradingAccount(data) assert result[0] == 0, u'调用api返回错误(result[0]=%d,result[1]=%s)' % ( result[0], result[1]) # 第1次调用api for i in range(10): result = traderChannel.QryTradingAccount(data) # 由于没有延迟设置所以调用不成功 if result[0] == -3: break else: raise Exception(u'没有发生预期的流量控制错误')
def __init__(self,frontAddress,brokerID,userID,password,nChannel=2,queryInterval=1): ''' 参数: frontAddress ctp服务器地址 brokerID 代理商编号 userID 用户编号 password 密码 nChannel 要建立的通道数,默认情况下为2 fileOutput ctp trader通讯进程的日志信息的保存路径,默认抛弃('/dev/null') ''' self.pool = [] for i in range(nChannel): traderPool = TraderChannel(frontAddress,brokerID,userID,password, queryInterval=queryInterval) self.pool.append(traderPool)
def setup(): ''' 所有用例的公共初始化代码 ''' global traderChannel,frontAddress,brokerID,userID,password # 读取环境变量中的信息 frontAddress = os.environ.get('CTP_FRONT_ADDRESS') assert frontAddress,u'必须定义环境变量:CTP_FRONT_ADDRESS' brokerID = os.environ.get('CTP_BROKER_ID') assert brokerID,u'必须定义环境变量:CTP_BROKER_ID' userID = os.environ.get('CTP_USER_ID') assert userID,u'必须定义环境变量:CTP_USER_ID' password = os.environ.get('CTP_PASSWORD') assert password,u'必须定义环境变量:CTP_PASSWORD' traderChannel = TraderChannel(frontAddress,brokerID,userID,password)
def test_ChannelClassUseWithStatment(): ''' 确认Channel相关对象可以使用with语句 ''' with TraderChannel(frontAddress, brokerID, userID, password) as traderChannel: assert traderChannel with TraderChannelPool(frontAddress, brokerID, userID, password) as traderChannelPool: assert traderChannelPool instrumentID = datetime.strftime(datetime.now() + relativedelta(months=1), "IF%y%m") with MdChannel(mdFrontAddress, brokerID, userID, password, [instrumentID]) as mdChannel: assert mdChannel
def test_ConverterQueryApiDelayMechanism(): ''' ''' # 模拟两个查询请求同时到达队列,但没有启用转换器的流量控制功能 # NOTE 默认情况下转换器流量控制延迟和queryInterval一致 traderChannel = TraderChannel(frontAddress, brokerID, userID, password, queryInterval=0) data = CThostFtdcQryTradingAccountField() # 由于将queryInterval设为0,破坏查询等待机制,需要等待一下,否则连第1个查询都会出错 sleep(1) # 连续调用2次查询api result = traderChannel.QryTradingAccount(data) assert result[0] == 0 for i in range(10): result = traderChannel.QryTradingAccount(data) # 由于没有延迟设置所以调用不成功 if result[0] == -3: break else: raise Exception(u'没有发生预期的流量控制错误') # 启动转换器的流量控制功能调用就能成功 traderChannel = TraderChannel(frontAddress, brokerID, userID, password, queryInterval=0, timeout=5, converterQueryInterval=1) data = CThostFtdcQryTradingAccountField() # 连续调用2次查询api result = traderChannel.QryTradingAccount(data) if result[0] != 0: print result[1] assert result[0] == 0 result = traderChannel.QryTradingAccount(data) if result[0] != 0: print result[1] assert result[0] == 0
def test_TraderChannelCleanCTPProcess(): ''' 测试TraderChannel是否能正常清理进程 ''' process = psutil.Process() # 没有创建TraderChannel对象前应该没有trader进程 #assert 'trader' not in [child.name() for child in process.children() ] # 创建后可以找到一个trader进程 traderChannel = TraderChannel(frontAddress, brokerID, userID, password) pid = traderChannel.traderProcess.pid assert pid and pid != 0 assert pid in [child.pid for child in process.children()] # 将变量指向None迫使垃圾回收,确认进程被清理了 traderChannel = None sleep(1) assert pid not in [child.pid for child in process.children()]
def test_OrderInsert_OpenAndClose(): ''' 测试报单 ''' # 创建交易通道 traderChannel = TraderChannel(frontAddress, brokerID, userID, password, timeout=1) print u'日志文件输出到:%s/trader.log' % traderChannel.workdir # 交易确认 requestData = CThostFtdcSettlementInfoConfirmField() requestData.BrokerID = brokerID requestData.InvestorID = userID result = traderChannel.SettlementInfoConfirm(requestData) assert result[0] == 0 # 尝试提交订单 requestData = getDefaultInputOrderField_buyOpen() result = traderChannel.OrderInsert(requestData) print result[0], result[1] assert result[0] in (0, -2003) if result[0] == -2003: # 非交易时段提交订单报此错误 return # 程序能到这里说明开仓成功 responseDataList = result[2] assert len(responseDataList) == 1 price0 = responseDataList[0].Price # 查询头寸 requestData = CThostFtdcQryInvestorPositionField() requestData.InstrumentID = getDefaultInstrumentID() requestData.Direction = '0' # 做多 result = traderChannel.QryInvestorPosition(requestData) print result[0], result[1] responseDataList = result[2] assert len(responseDataList) == 1 # 指定了品种和头寸方,应该只有一条记录 openVolume0 = responseDataList[0].OpenVolume closeVolume0 = responseDataList[0].CloseVolume print 'openVolume0=', openVolume0, ',closeVolume0=', closeVolume0 assert openVolume0 > 0 assert openVolume0 > closeVolume0 # 尝试进行平仓 requestData = getDefaultInputOrderField_buyClose() result = traderChannel.OrderInsert(requestData) assert result[0] == 0 responseDataList = result[2] assert len(responseDataList) == 1 price1 = responseDataList[0].Price # 查询头寸 requestData = CThostFtdcQryInvestorPositionField() requestData.InstrumentID = getDefaultInstrumentID() requestData.Direction = '0' # 做多 result = traderChannel.QryInvestorPosition(requestData) print result[0], result[1] responseData = result[2] assert len(responseData) == 1 # 指定了品种和头寸方,应该只有一条记录 openVolume1 = responseData[0].OpenVolume closeVolume1 = responseData[0].CloseVolume print 'openVolume1=', openVolume1, ',closeVolume1=', closeVolume1 assert openVolume0 == openVolume1 assert closeVolume1 - closeVolume0 == 1 print 'price0=', price0, 'price1=', price1 print 'diff=', price1 - price0
from datetime import datetime os.chdir(u'/home/duhan/github/pyctp') from CTPChannel import TraderChannel from CTPStruct import * from time import sleep frontAddress = os.environ.get('CTP_FRONT_ADDRESS') assert frontAddress brokerID = os.environ.get('CTP_BROKER_ID') assert brokerID userID = os.environ.get('CTP_USER_ID') assert userID password = os.environ.get('CTP_PASSWORD') assert password ch = TraderChannel(frontAddress,brokerID,userID,password,'/tmp/trader.log',1.1) data = CThostFtdcQryTradingAccountField() print ch.getQueryWaitTime() print ch.QryTradingAccount(data) #sleep(1) #print ch.QryTradingAccount(data) #print ch.QryTradingAccount(data) #print ch.QryTradingAccount(data) #print ch.QryTradingAccount(data) #print ch.QryTradingAccount(data) #(datetime.now() - ch.lastQueryTime).total_seconds() #for i in range(10): # print ch.QryTradingAccount(data) #%% 测试TraderChannelPool import os