#encoding=utf8
'''
Created on 2018年12月20日
@author: cdzq-xg
'''
import threading
import time
import re
import math
import random
class Pos(object):
def __init__(self):
self.position = 0
class Tick(object):
def __init__(self):
self.bidPrice1 = 0
self.askPrice1 = 0
'''
TWAP交易算法
'''
class twapAlgo(object):
def __init__(self):
self.tradeSecIDs= [] #股票交易列表
self.targetSecids = {} #组合信息(证券代码,日期,权重)
#self.timer = threading.Timer(1.0, self.OnTime)
#self.timer.start()
self.tradeTime = 5*60 #交易总时长(s)
self.SliptTime = 5 #拆单间隔
self.IfCancelNoBrag = False #是否撤回未成交委托,if true 重新下达委托
self.TrdMny = 0.0 #交易总金额
self.maxOrders = 5 #每秒的流量控制
self.timerCount = 0 #已交易时间
self.Trading = False #是否交易,当产生交易信号时,应该设为True
self.Pos = 0 #目的仓位,1是满仓,0是空仓
self.timerIx = 0 # 下标
self.minAmt = 1500.00 #每笔最小金额
self.minVol = 100 #每笔最小数量
self.finishedCount = 0 #交易完成的数量
self.holdpos = {}
'''
开始交易
'''
def BeginTrade(self):
wCount = len(self.tradeSecIDs)
if(wCount > 0):
#计算一轮需要多少时间
self.SliptTime = max( math.ceil( wCount / self.maxOrders),self.SliptTime)
self.Trading = True
self.timerCount = 0
self.finishedCount = 0
self.timerIx = 0
'''
结束交易,内部调用
'''
def _EndTrade(self):
self.Trading = False
self.timerCount = 0
self.finishedCount = 0
self.timerIx = 0
def getPosition(self,secid):
pos = Pos()
pos.position = self.holdpos[secid] if secid in self.holdpos.keys() else 0
return pos
def getTick(self,secid):
tick = Tick()
tick.askPrice1 = random.random(1.1,10.4)
tick.bidPrice1 = tick.askPrice1+ 0.01
tick.lastPrice = tick.bidPrice1
return tick
def sell(self,s,p,v):
print('%s 卖出%s,%s股,于%s' %(time.strftime('%Y-%m-%d %H:%M:%S'),s, v, p))
if s in self.holdpos.keys() and self.holdpos[s] > v:
self.holdpos[s] -= v
else:
self.holdpos[s] = 0
def buy(self,s,p,v):
print('%s 买入%s,%s股,于%s' %(time.strftime('%Y-%m-%d %H:%M:%S'),s, v, p))
if s in self.holdpos.keys():
self.holdpos[s] += v
else:
self.holdpos[s] = v
def writeLog(self,msg):
print(msg)
def cancelAll(self):
pass
'''
下一次委托
'''
def _downOnceOrds(self):
ordcount = 0
wCount = len(self.tradeSecIDs)
while(True):
#达到委托上限了
if ordcount >= self.maxOrders:
self.writeLog("order limited")
break
#全部已经交易完成 或者超时了
if self.finishedCount >= wCount:
self.writeLog("Finished.")
self._EndTrade()
break
if self.timerCount > self.tradeTime:
self.writeLog("time over.")
self._EndTrade()
break
#本轮已经委托完成了
if self.timerIx >= wCount:
self.timerIx = 0
break
# 查询当前股票持仓和目标仓位
vtSymbol = self.tradeSecIDs[self.timerIx]
#权重
weight = self.targetSecids[vtSymbol]
pos = self.getPosition(vtSymbol)
tick = self.getTick(vtSymbol)
if not tick:
self.writeLog('当前尚未收到%s的盘口数据' %vtSymbol)
self.timerIx += 1
continue
target = int(self.TrdMny * self.Pos * weight / tick.lastPrice / 100)*100
holdvol = pos.position if pos else 0
print(vtSymbol,holdvol,'-->',target)
# 如果持仓小于目标仓位,则执行买入
if holdvol < target:
#剩下的买入数量
volume = target - holdvol
#小于一百股,则认为是交易完成
if volume < 100:
self.finishedCount += 1
self.timerIx += 1
continue
# 以卖1价格挂单
price = tick.askPrice1
# 剩余时间
vtime = self.tradeTime - self.timerCount
# 剩余交易次数
vcount = int(vtime / self.SliptTime)
# 每次交易数量,如果只剩下2个交易间隔了,直接把剩下的数量全部下达下去
if vcount <= 2:
eachvol = int(volume/100)*100
else:
eachvol = int(volume/vcount/100)*100
vol = min(eachvol, int(volume/100)*100)
if vcount > 2 and( vol < self.minVol or vol*price < self.minAmt):
self.timerIx += 1
continue
# 买入委托
self.buy(vtSymbol, price, vol)
ordcount += 1
#self.timerIx += 1
self.writeLog(u'买入%s,%s股,价格%s' %(vtSymbol, vol, price))
# 如果持仓大于目标仓位,则执行卖出
elif holdvol > target:
#剩下的交易数量
volume = min(holdvol - target,pos.available)
if pos.available <= 0:
self.finishedCount += 1
self.timerIx += 1
continue
# 以买1价格挂单
price =tick.bidPrice1
# 剩余时间
vtime = self.tradeTime - self.timerCount
# 剩余交易次数
vcount = int(vtime / self.SliptTime)
# 每次交易数量
if vcount <= 2:
eachvol = volume
else:
eachvol = int(volume/vcount/100)*100
# 委托数量保证全成后持仓不会超过目标
vol = min(eachvol, volume)
if vcount > 2 and (vol < self.minVol or vol*price < self.minAmt):
self.timerIx += 1
continue
# 卖出委托
self.sell(vtSymbol, price, vol)
ordcount += 1
#self.timerIx += 1
self.writeLog(u'卖出%s,%s股,价格%s' %(vtSymbol, vol, price))
self.timerIx += 1
def OnTime(self):
#self.timer = threading.Timer(1.0, self.OnTime)
#self.timer.start()
self.timerCount += 1
#如果交易中
if self.Trading:
wCount = len(self.tradeSecIDs)
#如果一轮没有交易完,则每秒都需要下达委托
if self.timerIx % wCount > 0:
#print("一轮内交易")
self._downOnceOrds()
#新一轮拆单
elif (self.timerCount-1) % self.SliptTime==0:
#是否撤销未成交委托
if self.IfCancelNoBrag:
self.cancelAll()