2016-10-10 16:50:47 +00:00
|
|
|
|
# encoding: UTF-8
|
|
|
|
|
|
|
|
|
|
from vtConstant import *
|
|
|
|
|
from ctaBase import *
|
|
|
|
|
import talib as ta
|
|
|
|
|
|
|
|
|
|
from datetime import datetime
|
|
|
|
|
|
|
|
|
|
DEBUGCTALOG = True
|
|
|
|
|
|
|
|
|
|
class CtaPosition:
|
|
|
|
|
"""策略的仓位管理类
|
|
|
|
|
v 0.1 简单的数值,代表多仓数量和空仓数量
|
2017-04-30 14:21:14 +00:00
|
|
|
|
v 0.2 增加多仓和空仓的持仓,去除持仓均价
|
2016-10-10 16:50:47 +00:00
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
def __init__(self, strategy):
|
|
|
|
|
self.strategy = strategy
|
2017-04-30 14:21:14 +00:00
|
|
|
|
self.longPos = 0 # 多仓持仓
|
|
|
|
|
self.shortPos = 0 # 空仓持仓
|
|
|
|
|
self.pos = 0 # 持仓状态 0:空仓/对空平等; >=1 净多仓 ;<=-1 净空仓
|
|
|
|
|
self.maxPos = 1 # 最大持仓量(多仓+空仓总量)
|
2016-10-10 16:50:47 +00:00
|
|
|
|
self.step = 1 # 增仓数量
|
|
|
|
|
|
2017-04-30 14:21:14 +00:00
|
|
|
|
# disabled in v0.2
|
|
|
|
|
#self.posList = []
|
|
|
|
|
#self.avgPrice = EMPTY_FLOAT
|
2016-10-10 16:50:47 +00:00
|
|
|
|
|
|
|
|
|
def avaliablePos2Add(self):
|
|
|
|
|
"""剩余可加的仓位数量"""
|
2017-04-30 14:21:14 +00:00
|
|
|
|
return self.maxPos - abs(self.longPos) - abs(self.shortPos)
|
2016-10-10 16:50:47 +00:00
|
|
|
|
|
2017-04-30 14:21:14 +00:00
|
|
|
|
def openPos(self, direction, vol, price=EMPTY_FLOAT):
|
2016-10-10 16:50:47 +00:00
|
|
|
|
"""开、加仓"""
|
2017-04-30 14:21:14 +00:00
|
|
|
|
# vol: 正整数
|
|
|
|
|
|
|
|
|
|
# disabled in v0.2
|
|
|
|
|
#if self.pos == 0:
|
|
|
|
|
# self.posList = []
|
2016-10-10 16:50:47 +00:00
|
|
|
|
|
|
|
|
|
if direction == DIRECTION_LONG: # 加多仓
|
2017-04-30 14:21:14 +00:00
|
|
|
|
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。该方法不推荐使用
|
2016-10-10 16:50:47 +00:00
|
|
|
|
self.strategy.pos = self.pos
|
|
|
|
|
|
|
|
|
|
if direction == DIRECTION_SHORT: # 加空仓
|
2017-04-30 14:21:14 +00:00
|
|
|
|
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。该方法不推荐使用
|
2016-10-10 16:50:47 +00:00
|
|
|
|
self.strategy.pos = self.pos
|
|
|
|
|
|
2017-04-30 14:21:14 +00:00
|
|
|
|
# v0.2 disabled
|
|
|
|
|
#if price > EMPTY_FLOAT:
|
|
|
|
|
# self.posList.append(price)
|
2016-10-10 16:50:47 +00:00
|
|
|
|
|
|
|
|
|
# 计算持仓均价
|
2017-04-30 14:21:14 +00:00
|
|
|
|
#if len(self.posList) > 0:
|
|
|
|
|
# self.avgPrice = sum(self.posList)/len(self.posList)
|
|
|
|
|
# self.avgPrice = round(self.avgPrice, 3)
|
2016-10-10 16:50:47 +00:00
|
|
|
|
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
def closePos(self, direction, vol):
|
|
|
|
|
"""平、减仓"""
|
2017-04-30 14:21:14 +00:00
|
|
|
|
# vol: 正整数
|
2016-10-10 16:50:47 +00:00
|
|
|
|
|
|
|
|
|
if direction == DIRECTION_LONG: # 平空仓 Cover
|
2017-04-30 14:21:14 +00:00
|
|
|
|
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。该方法不推荐使用
|
2016-10-10 16:50:47 +00:00
|
|
|
|
self.strategy.pos = self.pos
|
|
|
|
|
|
|
|
|
|
if direction == DIRECTION_SHORT: # 平多仓
|
2017-04-30 14:21:14 +00:00
|
|
|
|
if self.longPos - vol < 0:
|
|
|
|
|
self.writeCtaError(u'异常,超出仓位。净:{0},多:{1},平仓:{2}'.format(self.pos, self.longPos, vol))
|
|
|
|
|
#self.strategy.pos = self.pos
|
|
|
|
|
#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.shortPos -= vol
|
|
|
|
|
self.pos -= vol
|
2016-10-10 16:50:47 +00:00
|
|
|
|
self.strategy.pos = self.pos
|
|
|
|
|
|
2017-04-30 14:21:14 +00:00
|
|
|
|
# disabled in v0.2
|
|
|
|
|
#if abs(self.pos) > 0:
|
|
|
|
|
# self.posList = self.posList[:-vol]
|
|
|
|
|
#else:
|
|
|
|
|
# self.posList = []
|
2016-10-10 16:50:47 +00:00
|
|
|
|
|
|
|
|
|
# 计算持仓均价
|
2017-04-30 14:21:14 +00:00
|
|
|
|
#if len(self.posList) > 0:
|
|
|
|
|
# self.avgPrice = sum(self.posList)/len(self.posList)
|
|
|
|
|
# self.avgPrice = round(self.avgPrice, 3)
|
2016-10-10 16:50:47 +00:00
|
|
|
|
|
|
|
|
|
return True
|
|
|
|
|
|
2017-04-30 14:21:14 +00:00
|
|
|
|
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)
|
|
|
|
|
|
2016-10-10 16:50:47 +00:00
|
|
|
|
# ----------------------------------------------------------------------
|
|
|
|
|
def writeCtaLog(self, content):
|
|
|
|
|
"""记录CTA日志"""
|
|
|
|
|
self.strategy.writeCtaLog(content)
|
|
|
|
|
|
2017-04-30 14:21:14 +00:00
|
|
|
|
def debugCtaLog(self, content):
|
2016-10-10 16:50:47 +00:00
|
|
|
|
"""记录CTA日志"""
|
|
|
|
|
if DEBUGCTALOG:
|
|
|
|
|
self.strategy.writeCtaLog('[DEBUG]'+content)
|
|
|
|
|
|