diff --git a/vn.trader/ctaStrategy/ctaPosition.py b/vn.trader/ctaStrategy/ctaPosition.py index f86fa867..0fbcb64b 100644 --- a/vn.trader/ctaStrategy/ctaPosition.py +++ b/vn.trader/ctaStrategy/ctaPosition.py @@ -11,98 +11,139 @@ DEBUGCTALOG = True class CtaPosition: """策略的仓位管理类 v 0.1 简单的数值,代表多仓数量和空仓数量 - + v 0.2 增加多仓和空仓的持仓,去除持仓均价 """ def __init__(self, strategy): self.strategy = strategy - - self.pos = 0 # 持仓状态 0:空仓 >=1 多仓 <=-1 空仓 - self.maxPos = 1 # 最大持仓量 + self.longPos = 0 # 多仓持仓 + self.shortPos = 0 # 空仓持仓 + self.pos = 0 # 持仓状态 0:空仓/对空平等; >=1 净多仓 ;<=-1 净空仓 + self.maxPos = 1 # 最大持仓量(多仓+空仓总量) self.step = 1 # 增仓数量 - self.posList = [] - self.avgPrice = EMPTY_FLOAT + # disabled in v0.2 + #self.posList = [] + #self.avgPrice = EMPTY_FLOAT def avaliablePos2Add(self): """剩余可加的仓位数量""" - return self.maxPos - abs(self.pos) + return self.maxPos - abs(self.longPos) - abs(self.shortPos) - def openPos(self, direction, vol, price = EMPTY_FLOAT): + def openPos(self, direction, vol, price=EMPTY_FLOAT): """开、加仓""" - if self.pos == 0: - self.posList = [] + # vol: 正整数 + + # disabled in v0.2 + #if self.pos == 0: + # self.posList = [] if direction == DIRECTION_LONG: # 加多仓 - if self.pos + vol > self.maxPos: - self.writeCtaLog(u'异常,超出仓位,当前仓位:{0},加仓:{1},最大仓位:{2}'.format(self.pos,vol,self.maxPos)) - return False - #print u'仓位:{0}->{1}'.format(self.pos, self.pos+vol) - self.writeCtaLog(u'仓位:{0}->{1}'.format(self.pos, self.pos+vol)) - self.pos = self.pos + vol + if (max(self.pos, self.longPos) + vol) > self.maxPos: + self.writeCtaError(u'异常,超出仓位。净:{0},多:{1},加多:{2},最大:{3}' + .format(self.pos, self.longPos, vol, self.maxPos)) + + # 只告警 + #return False + + # 更新 + self.writeCtaLog(u'多仓:{0}->{1}'.format(self.longPos, self.longPos + vol)) + self.writeCtaLog(u'净:{0}->{1}'.format(self.pos, self.pos + vol)) + self.longPos += vol + self.pos += vol + + # 更新上层策略的pos。该方法不推荐使用 self.strategy.pos = self.pos if direction == DIRECTION_SHORT: # 加空仓 - if self.pos - vol < 0 - self.maxPos: - self.writeCtaLog(u'异常,超出仓位,当前仓位:{0},加仓:{1},最大仓位:{2}'.format(self.pos, vol, self.maxPos)) - return False - #print u'仓位:{0}->{1}'.format(self.pos, self.pos-vol) - self.writeCtaLog(u'仓位:{0}->{1}'.format(self.pos, self.pos-vol)) - self.pos = self.pos - vol + if (min(self.pos, self.shortPos) - vol) < (0 - self.maxPos): + self.writeCtaError(u'异常,超出仓位。净:{0},空:{1},加空:{2},最大:{3}' + .format(self.pos, self.shortPos, vol, self.maxPos)) + #return False + + self.writeCtaLog(u'空仓:{0}->{1}'.format(self.shortPos, self.shortPos - vol)) + self.writeCtaLog(u'净:{0}->{1}'.format(self.pos, self.pos-vol)) + self.shortPos -= vol + self.pos -= vol + + # 更新上层策略的pos。该方法不推荐使用 self.strategy.pos = self.pos - if price > EMPTY_FLOAT: - self.posList.append(price) + # v0.2 disabled + #if price > EMPTY_FLOAT: + # self.posList.append(price) # 计算持仓均价 - if len(self.posList) > 0: - self.avgPrice = sum(self.posList)/len(self.posList) - self.avgPrice = round(self.avgPrice, 3) + #if len(self.posList) > 0: + # self.avgPrice = sum(self.posList)/len(self.posList) + # self.avgPrice = round(self.avgPrice, 3) return True def closePos(self, direction, vol): """平、减仓""" + # vol: 正整数 if direction == DIRECTION_LONG: # 平空仓 Cover - if self.pos + vol > 0: - self.writeCtaLog(u'异常,超出仓位,当前仓位:{0},平仓:{1}'.format(self.pos,vol)) - self.strategy.pos = self.pos - return False - #print u'仓位:{0}->{1}'.format(self.pos, self.pos+vol) - self.writeCtaLog(u'仓位:{0}->{1}'.format(self.pos, self.pos+vol)) - self.pos = self.pos + vol + if self.shortPos + vol > 0: + self.writeCtaError(u'异常,超出仓位。净:{0},空:{1},平仓:{2}'.format(self.pos, self.shortPos, vol)) + #self.strategy.pos = self.pos + #return False + + self.writeCtaLog(u'空仓:{0}->{1}'.format(self.shortPos, self.shortPos + vol)) + self.writeCtaLog(u'净:{0}->{1}'.format(self.pos, self.pos + vol)) + self.shortPos += vol + self.pos += vol + + # 更新上层策略的pos。该方法不推荐使用 self.strategy.pos = self.pos if direction == DIRECTION_SHORT: # 平多仓 - if self.pos - vol < 0 : - self.writeCtaLog(u'异常,超出仓位,当前仓位:{0},加仓:{1}'.format(self.pos, vol)) - self.strategy.pos = self.pos - return False + if self.longPos - vol < 0: + self.writeCtaError(u'异常,超出仓位。净:{0},多:{1},平仓:{2}'.format(self.pos, self.longPos, vol)) + #self.strategy.pos = self.pos + #return False - #print u'仓位:{0}->{1}'.format(self.pos, self.pos-vol) - self.writeCtaLog(u'仓位:{0}->{1}'.format(self.pos, self.pos-vol)) - self.pos = self.pos - vol + self.writeCtaLog(u'多仓:{0}->{1}'.format(self.longPos, self.longPos - vol)) + self.writeCtaLog(u'净:{0}->{1}'.format(self.pos, self.pos-vol)) + + self.shortPos -= vol + self.pos -= vol self.strategy.pos = self.pos - if abs(self.pos) > 0: - self.posList = self.posList[:-vol] - else: - self.posList = [] + # disabled in v0.2 + #if abs(self.pos) > 0: + # self.posList = self.posList[:-vol] + #else: + # self.posList = [] # 计算持仓均价 - if len(self.posList) > 0: - self.avgPrice = sum(self.posList)/len(self.posList) - self.avgPrice = round(self.avgPrice, 3) + #if len(self.posList) > 0: + # self.avgPrice = sum(self.posList)/len(self.posList) + # self.avgPrice = round(self.avgPrice, 3) return True + def clear(self): + """清除状态""" + self.writeCtaLog(u'清除所有持仓状态') + self.pos = 0 + self.longPos = 0 + self.shortPos = 0 + # 更新上层策略的pos + self.strategy.pos = 0 + + # ---------------------------------------------------------------------- + def writeCtaError(self, content): + """记录CTA日志错误""" + self.strategy.writeCtaLog(content) + # ---------------------------------------------------------------------- def writeCtaLog(self, content): """记录CTA日志""" self.strategy.writeCtaLog(content) - def debugCtaLog(self,content): + def debugCtaLog(self, content): """记录CTA日志""" if DEBUGCTALOG: self.strategy.writeCtaLog('[DEBUG]'+content)