# encoding: UTF-8 from __future__ import division import re from math import floor from datetime import datetime from vnpy.trader.vtConstant import (EMPTY_INT, EMPTY_FLOAT, EMPTY_STRING, EMPTY_UNICODE) EVENT_SPREADTRADING_TICK = 'eSpreadTradingTick.' EVENT_SPREADTRADING_POS = 'eSpreadTradingPos.' EVENT_SPREADTRADING_LOG = 'eSpreadTradingLog' EVENT_SPREADTRADING_ALGO = 'eSpreadTradingAlgo.' EVENT_SPREADTRADING_ALGOLOG = 'eSpreadTradingAlgoLog' ######################################################################## class StLeg(object): """""" #---------------------------------------------------------------------- def __init__(self): """Constructor""" self.vtSymbol = EMPTY_STRING # 代码 self.ratio = EMPTY_INT # 实际交易时的比例 self.multiplier = EMPTY_FLOAT # 计算价差时的乘数 self.payup = EMPTY_INT # 对冲时的超价tick self.bidPrice = EMPTY_FLOAT self.askPrice = EMPTY_FLOAT self.bidVolume = EMPTY_INT self.askVolume = EMPTY_INT self.longPos = EMPTY_INT self.shortPos = EMPTY_INT self.netPos = EMPTY_INT self.opcode = EMPTY_STRING self.legname = EMPTY_STRING ######################################################################## class StSpread(object): """""" #---------------------------------------------------------------------- def __init__(self): """Constructor""" self.name = EMPTY_UNICODE # 名称 self.symbol = EMPTY_STRING # 代码(基于组成腿计算) self.formula = EMPTY_STRING self.code =None self.activeLeg = None # 主动腿 self.passiveLegs = [] # 被动腿(支持多条) self.allLegs = [] # 所有腿 self.bidPrice = EMPTY_FLOAT self.askPrice = EMPTY_FLOAT self.bidVolume = EMPTY_INT self.askVolume = EMPTY_INT self.time = EMPTY_STRING self.longPos = EMPTY_INT self.shortPos = EMPTY_INT self.netPos = EMPTY_INT #---------------------------------------------------------------------- def initSpread(self): """初始化价差""" # 价差最少要有一条主动腿 if not self.activeLeg: return # 生成所有腿列表 self.allLegs.append(self.activeLeg) self.allLegs.extend(self.passiveLegs) # 生成价差代码 legSymbolList = [] self.symbol = self.formula for leg in self.allLegs: self.symbol = re.sub(leg.legname, leg.vtSymbol , self.symbol) #self.symbol = ''.join(legSymbolList) #---------------------------------------------------------------------- def calculatePrice(self): """计算价格""" # 清空价格和委托量数据 self.bidPrice = EMPTY_FLOAT self.askPrice = EMPTY_FLOAT self.askVolume = EMPTY_INT self.bidVolume = EMPTY_INT if not self.code : raise ValueError("Formula Error Can't Calculate Price") legbidglobal = {} legaskglobal = {} # 遍历价差腿列表 for n, leg in enumerate(self.allLegs): # 计算价格 if leg.askPrice == leg.bidPrice and leg.bidPrice == EMPTY_FLOAT: # 清空价格和委托量数据 self.bidPrice = EMPTY_FLOAT self.askPrice = EMPTY_FLOAT self.askVolume = EMPTY_INT self.bidVolume = EMPTY_INT else: if leg.ratio > 0: legbidglobal[leg.legname] = leg.bidPrice legaskglobal[leg.legname] = leg.askPrice else : legbidglobal[leg.legname] = leg.askPrice legaskglobal[leg.legname] = leg.bidPrice #tick数据有误,暂时不计算 #if leg.opcode == "add": #if leg.ratio > 0: #self.bidPrice += leg.bidPrice * leg.multiplier #self.askPrice += leg.askPrice * leg.multiplier #else: #self.bidPrice += leg.askPrice * leg.multiplier #self.askPrice += leg.bidPrice * leg.multiplier #elif leg.opcode == "div": #if n == 0 : #if leg.ratio > 0: #self.bidPrice = 1 / (leg.bidPrice * leg.multiplier) #self.askPrice = 1 / (leg.askPrice * leg.multiplier) #else: #self.bidPrice = 1 / (leg.askPrice * leg.multiplier) #self.askPrice = 1 / (leg.bidPrice * leg.multiplier) #else: #if leg.ratio > 0: #self.bidPrice = self.bidPrice / (leg.bidPrice * leg.multiplier) #self.askPrice = self.askPrice / (leg.askPrice * leg.multiplier) #else: #self.bidPrice = self.bidPrice / (leg.askPrice * leg.multiplier) #self.askPrice = self.askPrice / (leg.bidPrice * leg.multiplier) #elif leg.opcode == "mul": #if n == 0 : #if leg.ratio > 0: #self.bidPrice = (leg.bidPrice * leg.multiplier) #self.askPrice = (leg.askPrice * leg.multiplier) #else: #self.bidPrice = (leg.bidPrice * leg.multiplier) #self.askPrice = (leg.askPrice * leg.multiplier) #else: #if leg.ratio > 0: #self.bidPrice = self.bidPrice * (leg.bidPrice * leg.multiplier) #self.askPrice = self.askPrice * (leg.askPrice * leg.multiplier) #else: #self.bidPrice = self.bidPrice * (leg.askPrice * leg.multiplier) #self.askPrice = self.askPrice * (leg.bidPrice * leg.multiplier) # 计算报单量 if leg.ratio > 0: legAdjustedBidVolume = floor(leg.bidVolume / leg.ratio) legAdjustedAskVolume = floor(leg.askVolume / leg.ratio) else: legAdjustedBidVolume = floor(leg.askVolume / abs(leg.ratio)) legAdjustedAskVolume = floor(leg.bidVolume / abs(leg.ratio)) if n == 0: self.bidVolume = legAdjustedBidVolume # 对于第一条腿,直接初始化 self.askVolume = legAdjustedAskVolume else: self.bidVolume = min(self.bidVolume, legAdjustedBidVolume) # 对于后续的腿,价差可交易报单量取较小值 self.askVolume = min(self.askVolume, legAdjustedAskVolume) bidok = True askok = True for k in self.code.co_names : bidok = bidok and k in legbidglobal askok = askok and k in legaskglobal if bidok and askok : self.bidPrice = eval(self.code,legbidglobal) self.askPrice = eval(self.code,legaskglobal) # 更新时间 self.time = datetime.now().strftime('%H:%M:%S.%f')[:-3] #---------------------------------------------------------------------- def calculatePos(self): """计算持仓""" # 清空持仓数据 self.longPos = EMPTY_INT self.shortPos = EMPTY_INT self.netPos = EMPTY_INT # 遍历价差腿列表 for n, leg in enumerate(self.allLegs): if leg.ratio > 0: legAdjustedLongPos = floor(leg.longPos / leg.ratio) legAdjustedShortPos = floor(leg.shortPos / leg.ratio) else: legAdjustedLongPos = floor(leg.shortPos / abs(leg.ratio)) legAdjustedShortPos = floor(leg.longPos / abs(leg.ratio)) if n == 0: self.longPos = legAdjustedLongPos self.shortPos = legAdjustedShortPos else: self.longPos = min(self.longPos, legAdjustedLongPos) self.shortPos = min(self.shortPos, legAdjustedShortPos) # 计算净仓位 self.longPos = int(self.longPos) self.shortPos = int(self.shortPos) self.netPos = self.longPos - self.shortPos #---------------------------------------------------------------------- def addActiveLeg(self, leg): """添加主动腿""" self.activeLeg = leg #---------------------------------------------------------------------- def addPassiveLeg(self, leg): """添加被动腿""" self.passiveLegs.append(leg)