[Add]初步完成OptionMaster核心定价部分的开发
This commit is contained in:
parent
a4394d2baa
commit
64bd2eb6d2
@ -1 +1 @@
|
|||||||
PurwJxAEvTeQ9X8HMnmMRw==
|
B7/DvEptJ5IBD1LIj9SEFg==
|
@ -19,7 +19,7 @@ from vnpy.trader.uiMainWindow import MainWindow
|
|||||||
from vnpy.trader.gateway import (secGateway)
|
from vnpy.trader.gateway import (secGateway)
|
||||||
|
|
||||||
# 加载上层应用
|
# 加载上层应用
|
||||||
from vnpy.trader.app import (riskManager)
|
from vnpy.trader.app import (riskManager, optionMaster)
|
||||||
|
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
@ -39,6 +39,7 @@ def main():
|
|||||||
|
|
||||||
# 添加上层应用
|
# 添加上层应用
|
||||||
me.addApp(riskManager)
|
me.addApp(riskManager)
|
||||||
|
me.addApp(optionMaster)
|
||||||
|
|
||||||
# 创建主窗口
|
# 创建主窗口
|
||||||
mw = MainWindow(me, ee)
|
mw = MainWindow(me, ee)
|
||||||
|
0
vnpy/pricing/__init__.py
Normal file
0
vnpy/pricing/__init__.py
Normal file
@ -23,6 +23,7 @@ theta:当t变动1天时,price的变动(国内交易日每年240天)
|
|||||||
vega:当v涨跌1个点时,price的变动(如从16%涨到17%)
|
vega:当v涨跌1个点时,price的变动(如从16%涨到17%)
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
from __future__ import division
|
||||||
|
|
||||||
from scipy import stats
|
from scipy import stats
|
||||||
from math import (log, pow, sqrt, exp)
|
from math import (log, pow, sqrt, exp)
|
||||||
@ -74,9 +75,15 @@ def calculateTheta(f, k, r, t, v, cp):
|
|||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
def calculateVega(f, k, r, t, v, cp):
|
def calculateVega(f, k, r, t, v, cp):
|
||||||
"""计算Vega值"""
|
"""计算Vega值"""
|
||||||
|
vega = calculateVega(f, k, r, t, v, cp) / 100
|
||||||
|
return vega
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
def calculateOriginalVega(f, k, r, t, v, cp):
|
||||||
|
"""计算原始vega值"""
|
||||||
price1 = calculatePrice(f, k, r, t, v*STEP_UP, cp)
|
price1 = calculatePrice(f, k, r, t, v*STEP_UP, cp)
|
||||||
price2 = calculatePrice(f, k, r, t, v*STEP_DOWN, cp)
|
price2 = calculatePrice(f, k, r, t, v*STEP_DOWN, cp)
|
||||||
vega = (price1 - price2) / (v * STEP_DIFF * 100)
|
vega = (price1 - price2) / (v * STEP_DIFF)
|
||||||
return vega
|
return vega
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
@ -109,12 +116,13 @@ def calculateImpv(price, f, k, r, t, cp):
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
# 采用Newton Raphson方法计算隐含波动率
|
# 采用Newton Raphson方法计算隐含波动率
|
||||||
v = 0.2 # 初始波动率猜测
|
v = 0.3 # 初始波动率猜测
|
||||||
|
|
||||||
for i in range(50):
|
for i in range(50):
|
||||||
# 计算当前猜测波动率对应的期权价格和vega值
|
# 计算当前猜测波动率对应的期权价格和vega值
|
||||||
p = calculatePrice(f, k, r, t, v, cp)
|
p = calculatePrice(f, k, r, t, v, cp)
|
||||||
vega = calculateVega(f, k, r, t, v, cp)
|
#print 'calculating vega', f, k, r, t, v, cp
|
||||||
|
vega = calculateOriginalVega(f, k, r, t, v, cp)
|
||||||
|
|
||||||
# 计算误差
|
# 计算误差
|
||||||
dx = (price - p) / vega
|
dx = (price - p) / vega
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
# encoding: UTF-8
|
# encoding: UTF-8
|
||||||
|
|
||||||
#from rmEngine import RmEngine
|
from .omEngine import OmEngine
|
||||||
#from uiRmWidget import RmEngineManager
|
from .uiOmWidget import OmManager
|
||||||
|
|
||||||
appName = 'OptionMaster'
|
appName = 'OptionMaster'
|
||||||
appDisplayName = u'OptionMaster'
|
appDisplayName = u'OptionMaster'
|
||||||
appEngine = None
|
appEngine = OmEngine
|
||||||
appWidget = None
|
appWidget = OmManager
|
||||||
appIco = 'om.ico'
|
appIco = 'om.ico'
|
@ -2,19 +2,18 @@
|
|||||||
"name": "etf_portfolio",
|
"name": "etf_portfolio",
|
||||||
"model": "black",
|
"model": "black",
|
||||||
"underlying": [
|
"underlying": [
|
||||||
"IH1711",
|
"510050"
|
||||||
"IH1712"
|
|
||||||
],
|
],
|
||||||
"chain": [
|
"chain": [
|
||||||
{
|
{
|
||||||
"underlyingSymbol": "IH1711",
|
"underlyingSymbol": "510050",
|
||||||
"chainSymbol": "m1709",
|
"chainSymbol": "510050-1712",
|
||||||
"interestRate": 0.03,
|
"r": 0.03
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"underlyingSymbol": "IH1711",
|
"underlyingSymbol": "510050",
|
||||||
"chainSymbol": "m1801",
|
"chainSymbol": "510050-1801",
|
||||||
"interestRate": 0.03,
|
"r": 0.03
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
@ -1,5 +1,7 @@
|
|||||||
# encoding: UTF-8
|
# encoding: UTF-8
|
||||||
|
|
||||||
|
from __future__ import division
|
||||||
|
|
||||||
from copy import copy
|
from copy import copy
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
|
||||||
@ -26,7 +28,10 @@ class OmInstrument(VtTickData):
|
|||||||
"""Constructor"""
|
"""Constructor"""
|
||||||
super(OmInstrument, self).__init__()
|
super(OmInstrument, self).__init__()
|
||||||
|
|
||||||
|
self.tickInited = False
|
||||||
|
|
||||||
# 初始化合约信息
|
# 初始化合约信息
|
||||||
|
self.symbol = contract.symbol
|
||||||
self.exchange = contract.exchange
|
self.exchange = contract.exchange
|
||||||
self.vtSymbol = contract.vtSymbol
|
self.vtSymbol = contract.vtSymbol
|
||||||
|
|
||||||
@ -38,10 +43,15 @@ class OmInstrument(VtTickData):
|
|||||||
self.midPrice = EMPTY_FLOAT
|
self.midPrice = EMPTY_FLOAT
|
||||||
|
|
||||||
# 持仓数据
|
# 持仓数据
|
||||||
self.longPos = detail.longPos
|
self.longPos = 0
|
||||||
self.shortPos = detail.shortPos
|
self.shortPos = 0
|
||||||
self.netPos = self.longPos - self.shortPos
|
self.netPos = 0
|
||||||
|
|
||||||
|
if detail:
|
||||||
|
self.longPos = detail.longPos
|
||||||
|
self.shortPos = detail.shortPos
|
||||||
|
self.netPos = self.longPos - self.shortPos
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
def newTick(self, tick):
|
def newTick(self, tick):
|
||||||
"""行情更新"""
|
"""行情更新"""
|
||||||
@ -61,6 +71,7 @@ class OmInstrument(VtTickData):
|
|||||||
self.askPrice1 = tick.askPrice1
|
self.askPrice1 = tick.askPrice1
|
||||||
self.bidVolume1 = tick.bidVolume1
|
self.bidVolume1 = tick.bidVolume1
|
||||||
self.askVolume1 = tick.askVolume1
|
self.askVolume1 = tick.askVolume1
|
||||||
|
self.midPrice = (self.bidPrice1 + self.askPrice1) / 2
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
def newTrade(self, trade):
|
def newTrade(self, trade):
|
||||||
@ -98,17 +109,22 @@ class OmUnderlying(OmInstrument):
|
|||||||
"""标的物"""
|
"""标的物"""
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
def __init__(self, contract, chainList):
|
def __init__(self, contract, detail, chainList=None):
|
||||||
"""Constructor"""
|
"""Constructor"""
|
||||||
super(OmUnderlying, self).__init__(contract)
|
super(OmUnderlying, self).__init__(contract, detail)
|
||||||
|
|
||||||
# 以该合约为标的物的期权链字典
|
# 以该合约为标的物的期权链字典
|
||||||
self.chainDict = OrderedDict((chain.symbol, chain) for chain in chainList)
|
self.chainDict = OrderedDict()
|
||||||
|
|
||||||
# 希腊值
|
# 希腊值
|
||||||
self.theoDelta = EMPTY_FLOAT # 理论delta值
|
self.theoDelta = EMPTY_FLOAT # 理论delta值
|
||||||
self.posDelta = EMPTY_FLOAT # 持仓delta值
|
self.posDelta = EMPTY_FLOAT # 持仓delta值
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
def addChain(self, chain):
|
||||||
|
"""添加以该合约为标的的期权链"""
|
||||||
|
self.chainDict[chain.symbol] = chain
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
def newTick(self, tick):
|
def newTick(self, tick):
|
||||||
"""行情更新"""
|
"""行情更新"""
|
||||||
@ -117,7 +133,7 @@ class OmUnderlying(OmInstrument):
|
|||||||
self.theoDelta = self.size * self.midPrice / 100
|
self.theoDelta = self.size * self.midPrice / 100
|
||||||
|
|
||||||
# 遍历推送自己的行情到期权链中
|
# 遍历推送自己的行情到期权链中
|
||||||
for chain in self.chainList:
|
for chain in self.chainDict.values():
|
||||||
chain.newUnderlyingTick()
|
chain.newUnderlyingTick()
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
@ -137,12 +153,12 @@ class OmOption(OmInstrument):
|
|||||||
"""期权"""
|
"""期权"""
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
def __init__(self, contract, underlying, model, r):
|
def __init__(self, contract, detail, underlying, model, r):
|
||||||
"""Constructor"""
|
"""Constructor"""
|
||||||
super(OmOption, self).__init__(contract)
|
super(OmOption, self).__init__(contract, detail)
|
||||||
|
|
||||||
# 期权属性
|
# 期权属性
|
||||||
self.underlying = None # 标的物对象
|
self.underlying = underlying # 标的物对象
|
||||||
self.k = contract.strikePrice # 行权价
|
self.k = contract.strikePrice # 行权价
|
||||||
self.r = r # 利率
|
self.r = r # 利率
|
||||||
|
|
||||||
@ -183,7 +199,7 @@ class OmOption(OmInstrument):
|
|||||||
self.chain = None
|
self.chain = None
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
def calculateImpv(self):
|
def calculateOptionImpv(self):
|
||||||
"""计算隐含波动率"""
|
"""计算隐含波动率"""
|
||||||
underlyingPrice = self.underlying.midPrice
|
underlyingPrice = self.underlying.midPrice
|
||||||
if not underlyingPrice:
|
if not underlyingPrice:
|
||||||
@ -222,12 +238,12 @@ class OmOption(OmInstrument):
|
|||||||
def newTick(self, tick):
|
def newTick(self, tick):
|
||||||
"""行情更新"""
|
"""行情更新"""
|
||||||
super(OmOption, self).newTick(tick)
|
super(OmOption, self).newTick(tick)
|
||||||
self.calculateImpv()
|
self.calculateOptionImpv()
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
def newUnderlyingTick(self):
|
def newUnderlyingTick(self):
|
||||||
"""标的行情更新"""
|
"""标的行情更新"""
|
||||||
self.calculateImpv()
|
self.calculateOptionImpv()
|
||||||
self.calculateTheoGreeks()
|
self.calculateTheoGreeks()
|
||||||
self.calculatePosGreeks()
|
self.calculatePosGreeks()
|
||||||
|
|
||||||
@ -243,7 +259,6 @@ class OmOption(OmInstrument):
|
|||||||
self.underlying = underlying
|
self.underlying = underlying
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
class OmChain(object):
|
class OmChain(object):
|
||||||
"""期权链"""
|
"""期权链"""
|
||||||
@ -394,10 +409,10 @@ class OmPortfolio(object):
|
|||||||
self.posTheta = 0
|
self.posTheta = 0
|
||||||
self.posVega = 0
|
self.posVega = 0
|
||||||
|
|
||||||
for underlying in self.underlyingList:
|
for underlying in self.underlyingDict.values():
|
||||||
self.posDelta += underlying.posDelta
|
self.posDelta += underlying.posDelta
|
||||||
|
|
||||||
for chain in self.chainList:
|
for chain in self.chainDict.values():
|
||||||
self.longPos += chain.longPos
|
self.longPos += chain.longPos
|
||||||
self.shortPos += chain.shortPos
|
self.shortPos += chain.shortPos
|
||||||
|
|
||||||
|
@ -5,16 +5,26 @@ import json
|
|||||||
import shelve
|
import shelve
|
||||||
import os
|
import os
|
||||||
import traceback
|
import traceback
|
||||||
|
from collections import OrderedDict
|
||||||
|
|
||||||
from vnpy.event import Event
|
from vnpy.event import Event
|
||||||
from vnpy.trader.vtEvent import EVENT_TICK, EVENT_TRADE, EVENT_CONTRACT
|
from vnpy.trader.vtEvent import EVENT_TICK, EVENT_TRADE, EVENT_CONTRACT
|
||||||
from vnpy.trader.vtFunction import getTempPath, getJsonPath
|
from vnpy.trader.vtFunction import getTempPath, getJsonPath
|
||||||
from vnpy.trader.vtObject import VtLogData
|
from vnpy.trader.vtObject import VtLogData, VtSubscribeReq
|
||||||
|
from vnpy.trader.vtConstant import PRODUCT_OPTION, OPTION_CALL, OPTION_PUT
|
||||||
|
from vnpy.pricing import black
|
||||||
|
|
||||||
from .omBase import (OmOption, OmUnderlying, OmChain, OmPortfolio,
|
from .omBase import (OmOption, OmUnderlying, OmChain, OmPortfolio,
|
||||||
EVENT_OM_LOG)
|
EVENT_OM_LOG)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# 定价模型字典
|
||||||
|
MODEL_DICT = {}
|
||||||
|
MODEL_DICT['black'] = black
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
class OmEngine(object):
|
class OmEngine(object):
|
||||||
"""期权主引擎"""
|
"""期权主引擎"""
|
||||||
@ -28,7 +38,7 @@ class OmEngine(object):
|
|||||||
self.eventEngine = eventEngine
|
self.eventEngine = eventEngine
|
||||||
|
|
||||||
self.portfolio = None
|
self.portfolio = None
|
||||||
self.contractDict = {} # symbol:contract
|
self.optionContractDict = {} # symbol:contract
|
||||||
|
|
||||||
self.registerEvent()
|
self.registerEvent()
|
||||||
|
|
||||||
@ -53,18 +63,22 @@ class OmEngine(object):
|
|||||||
def processContractEvent(self, event):
|
def processContractEvent(self, event):
|
||||||
"""合约事件"""
|
"""合约事件"""
|
||||||
contract = event.dict_['data']
|
contract = event.dict_['data']
|
||||||
if contract.symbol:
|
if contract.symbol and contract.productClass == PRODUCT_OPTION:
|
||||||
self.contractDict[contract.symbol] = contract
|
self.optionContractDict[contract.symbol] = contract
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
def subscribeEvent(self, symbol):
|
def subscribeEvent(self, symbol):
|
||||||
"""订阅对应合约的事件"""
|
"""订阅对应合约的事件"""
|
||||||
contract = self.contractDict[symbol]
|
contract = self.mainEngine.getContract(symbol)
|
||||||
|
if not contract:
|
||||||
|
self.writeLog(u'行情订阅失败,找不到合约:%s' %symbol)
|
||||||
|
return
|
||||||
|
|
||||||
vtSymbol = contract.vtSymbol
|
vtSymbol = contract.vtSymbol
|
||||||
|
|
||||||
# 订阅行情
|
# 订阅行情
|
||||||
req = VtSubscribeReq()
|
req = VtSubscribeReq()
|
||||||
req.symbol = symbol
|
req.symbol = contract.symbol
|
||||||
req.exchange = contract.exchange
|
req.exchange = contract.exchange
|
||||||
self.mainEngine.subscribe(req, contract.gatewayName)
|
self.mainEngine.subscribe(req, contract.gatewayName)
|
||||||
|
|
||||||
@ -80,67 +94,81 @@ class OmEngine(object):
|
|||||||
|
|
||||||
f = file(fileName)
|
f = file(fileName)
|
||||||
setting = json.load(f)
|
setting = json.load(f)
|
||||||
|
|
||||||
|
# 读取定价模型
|
||||||
|
model = MODEL_DICT.get(setting['model'], None)
|
||||||
|
if not model:
|
||||||
|
self.writeLog(u'找不到定价模型%s' %setting['model'])
|
||||||
|
return
|
||||||
|
|
||||||
# 创建期货和股票标的对象
|
# 创建标的对象
|
||||||
equityDict = OrderedDict([(symbol, OmEquity(symbol)) for symbol in setting['equity']])
|
underlyingDict = OrderedDict()
|
||||||
futuresDict = OrderedDict([(symbol, OmFutures(symbol)) for symbol in setting['futures']])
|
|
||||||
|
for underlyingSymbol in setting['underlying']:
|
||||||
|
contract = self.mainEngine.getContract(underlyingSymbol)
|
||||||
|
if not contract:
|
||||||
|
self.writeLog(u'找不到标的物合约%s' %underlyingSymbol)
|
||||||
|
continue
|
||||||
|
|
||||||
|
detail = self.mainEngine.getPositionDetail(contract.vtSymbol)
|
||||||
|
|
||||||
|
underlying = OmUnderlying(contract, detail)
|
||||||
|
underlyingDict[underlyingSymbol] = underlying
|
||||||
|
|
||||||
# 创建期权链对象并初始化
|
# 创建期权链对象并初始化
|
||||||
chainDict = OrderedDict()
|
chainList = []
|
||||||
|
|
||||||
for d in setting['chain']:
|
for d in setting['chain']:
|
||||||
interestRate = d['interestRate']
|
chainSymbol = d['chainSymbol']
|
||||||
|
r = d['r']
|
||||||
|
|
||||||
# 锁定标的对象,若无则创建
|
# 锁定标的对象
|
||||||
if d['underlyingType'] == 'futures':
|
underlying = underlyingDict.get(d['underlyingSymbol'], None)
|
||||||
if d['underlyingSymbol'] not in futuresDict:
|
if not underlying:
|
||||||
underlying = OmFutures(d['underlyingSymbol'])
|
self.writeLog(u'%s期权链的标的合约%s尚未创建,请检查配置文件' %(chainSymbol, underlyingSymbol))
|
||||||
futuresDict[underlying.symbol] = underlying
|
continue
|
||||||
else:
|
|
||||||
underlying = futuresDict[d['underlyingSymbol']]
|
|
||||||
elif d['underlyingType'] == 'equity':
|
|
||||||
if d['underlyingSymbol'] not in equityDict:
|
|
||||||
underlying = OmEquity(d['underlyingSymbol'])
|
|
||||||
equityDict[underlying.symbol] = underlying
|
|
||||||
else:
|
|
||||||
underlying = equityDict[d['underlyingSymbol']]
|
|
||||||
|
|
||||||
# 创建期权对象并初始化
|
# 创建期权对象并初始化
|
||||||
callList = []
|
callDict = {}
|
||||||
putList = []
|
putDict = {}
|
||||||
|
|
||||||
for symbol, contract in self.contractDict.items():
|
for symbol, contract in self.optionContractDict.items():
|
||||||
if contract.optionType and contract.underlyingSymbol == d['chainSymbol']:
|
if contract.underlyingSymbol == d['chainSymbol']:
|
||||||
option = OmOption(symbol)
|
detail = self.mainEngine.getPositionDetail(contract.vtSymbol)
|
||||||
option.init(contract, underlying, interestRate)
|
option = OmOption(contract, detail, underlying, model, r)
|
||||||
self.subscribeEvent(option.symbol) # 订阅事件
|
|
||||||
|
|
||||||
if contract.optionType is OPTION_CALL:
|
if contract.optionType is OPTION_CALL:
|
||||||
callList.append(option)
|
callDict[option.k] = option
|
||||||
else:
|
else:
|
||||||
putList.append(option)
|
putDict[option.k] = option
|
||||||
|
|
||||||
|
# 期权排序
|
||||||
|
strikeList = callDict.keys()
|
||||||
|
strikeList.sort()
|
||||||
|
callList = [callDict[k] for k in strikeList]
|
||||||
|
putList = [putDict[k] for k in strikeList]
|
||||||
|
|
||||||
|
# 创建期权链
|
||||||
|
chain = OmChain(chainSymbol, callList, putList)
|
||||||
|
chainList.append(chain)
|
||||||
|
|
||||||
|
# 添加标的映射关系
|
||||||
|
underlying.addChain(chain)
|
||||||
|
|
||||||
chain = OmChain(d['chainSymbol'])
|
|
||||||
chain.init(underlying, callList, putList)
|
|
||||||
chainDict[chain.symbol] = chain
|
|
||||||
|
|
||||||
# 初始化标的对象
|
|
||||||
for underlying in (equityDict.values() + futuresDict.values()):
|
|
||||||
l = []
|
|
||||||
for chain in chainDict.values():
|
|
||||||
if chain.underlying is underlying:
|
|
||||||
l.append(chain)
|
|
||||||
contract = self.contractDict[underlying.symbol]
|
|
||||||
underlying.init(contract, l)
|
|
||||||
self.subscribeEvent(underlying.symbol) # 订阅事件
|
|
||||||
|
|
||||||
# 创建持仓组合对象并初始化
|
# 创建持仓组合对象并初始化
|
||||||
self.portfolio = OmPortfolio(setting['name'])
|
self.portfolio = OmPortfolio(setting['name'], underlyingDict.values(), chainList)
|
||||||
self.portfolio.init(futuresDict, equityDict, chainDict)
|
|
||||||
|
|
||||||
# 载入波动率配置
|
# 载入波动率配置
|
||||||
self.loadImpvSetting()
|
self.loadImpvSetting()
|
||||||
|
|
||||||
|
# 订阅行情和事件
|
||||||
|
for underlying in underlyingDict.values():
|
||||||
|
self.subscribeEvent(underlying.vtSymbol)
|
||||||
|
|
||||||
|
for chain in chainList:
|
||||||
|
for option in chain.optionDict.values():
|
||||||
|
self.subscribeEvent(option.vtSymbol)
|
||||||
|
|
||||||
# 载入成功返回
|
# 载入成功返回
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
123
vnpy/trader/app/optionMaster/uiOmWidget.py
Normal file
123
vnpy/trader/app/optionMaster/uiOmWidget.py
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
# encoding: UTF-8
|
||||||
|
|
||||||
|
from __future__ import division
|
||||||
|
|
||||||
|
import os
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
from vnpy.event import Event
|
||||||
|
from vnpy.trader.uiQt import QtWidgets, QtCore
|
||||||
|
|
||||||
|
from .omBase import EVENT_OM_LOG
|
||||||
|
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
class OmManager(QtWidgets.QWidget):
|
||||||
|
"""管理组件"""
|
||||||
|
signal = QtCore.pyqtSignal(type(Event()))
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
def __init__(self, omEngine, eventEngine, parent=None):
|
||||||
|
"""Constructor"""
|
||||||
|
super(OmManager, self).__init__(parent)
|
||||||
|
|
||||||
|
self.omEngine = omEngine
|
||||||
|
self.eventEngine = eventEngine
|
||||||
|
|
||||||
|
self.widgetDict = {}
|
||||||
|
|
||||||
|
self.initUi()
|
||||||
|
self.registerEvent()
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
def initUi(self):
|
||||||
|
"""初始化界面"""
|
||||||
|
self.setWindowTitle(u'OptionMaster管理')
|
||||||
|
|
||||||
|
# 读取配置文件
|
||||||
|
settingFileList = []
|
||||||
|
|
||||||
|
path = os.path.abspath(os.path.dirname(__file__))
|
||||||
|
for root, subdirs, files in os.walk(path):
|
||||||
|
for name in files:
|
||||||
|
if '_portfolio.json' in name:
|
||||||
|
settingFileList.append(name)
|
||||||
|
|
||||||
|
# 设置界面
|
||||||
|
self.comboSettingFile = QtWidgets.QComboBox()
|
||||||
|
self.comboSettingFile.addItems(settingFileList)
|
||||||
|
self.comboSettingFile.setCurrentIndex(0)
|
||||||
|
|
||||||
|
self.buttonInit = QtWidgets.QPushButton(u'初始化')
|
||||||
|
self.buttonInit.clicked.connect(self.initOmEngine)
|
||||||
|
|
||||||
|
self.logMonitor = QtWidgets.QTextEdit()
|
||||||
|
self.logMonitor.setReadOnly(True)
|
||||||
|
|
||||||
|
hbox = QtWidgets.QHBoxLayout()
|
||||||
|
hbox.addWidget(self.comboSettingFile)
|
||||||
|
hbox.addWidget(self.buttonInit)
|
||||||
|
hbox.addStretch()
|
||||||
|
|
||||||
|
hbox2 = QtWidgets.QHBoxLayout()
|
||||||
|
hbox2.addStretch()
|
||||||
|
|
||||||
|
vbox = QtWidgets.QVBoxLayout()
|
||||||
|
vbox.addLayout(hbox)
|
||||||
|
vbox.addLayout(hbox2)
|
||||||
|
vbox.addWidget(self.logMonitor)
|
||||||
|
|
||||||
|
self.setLayout(vbox)
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
def initOmEngine(self):
|
||||||
|
"""初始化引擎"""
|
||||||
|
path = os.path.abspath(os.path.dirname(__file__))
|
||||||
|
fileName = unicode(self.comboSettingFile.currentText())
|
||||||
|
fileName = os.path.join(path, fileName)
|
||||||
|
result = self.omEngine.initEngine(fileName)
|
||||||
|
|
||||||
|
if result:
|
||||||
|
self.writeLog(u'引擎初始化成功')
|
||||||
|
else:
|
||||||
|
self.writeLog(u'请勿重复初始化引擎')
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
def writeLog(self, content, time=''):
|
||||||
|
"""记录日志"""
|
||||||
|
if not time:
|
||||||
|
time = datetime.now().strftime('%H:%M:%S')
|
||||||
|
content = time + '\t' + content
|
||||||
|
self.logMonitor.append(content)
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
def processLogEvent(self, event):
|
||||||
|
"""处理日志事件"""
|
||||||
|
log = event.dict_['data']
|
||||||
|
self.writeLog(log.logContent, log.logTime)
|
||||||
|
self.raise_()
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
def openManualTrader(self):
|
||||||
|
"""打开手动交易"""
|
||||||
|
try:
|
||||||
|
self.widgetDict['manualTrader'].showMaximized()
|
||||||
|
except KeyError:
|
||||||
|
self.widgetDict['manualTrader'] = ManualTrader(self.omEngine)
|
||||||
|
self.widgetDict['manualTrader'].showMaximized()
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
def close(self):
|
||||||
|
"""关闭"""
|
||||||
|
for widget in self.widgetDict.values():
|
||||||
|
widget.close()
|
||||||
|
|
||||||
|
super(OmManagerWidget, self).close()
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
def registerEvent(self):
|
||||||
|
"""注册事件监听"""
|
||||||
|
self.signal.connect(self.processLogEvent)
|
||||||
|
|
||||||
|
self.eventEngine.register(EVENT_OM_LOG, self.signal.emit)
|
||||||
|
|
@ -50,8 +50,11 @@ exchangeMapReverse = {v:k for k,v in exchangeMap.items()}
|
|||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
def print_dict(d):
|
def print_dict(d):
|
||||||
""""""
|
""""""
|
||||||
for k, v in d.items():
|
print '-' * 30
|
||||||
print '%s:%s' %(k, v)
|
l = d.keys()
|
||||||
|
l.sort()
|
||||||
|
for k in l:
|
||||||
|
print '%s:%s' %(k, d[k])
|
||||||
|
|
||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
@ -893,7 +896,7 @@ class SecTdApi(TdApi):
|
|||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
def onRspStockQryStockStaticInfo(self, data, error, flag):
|
def onRspStockQryStockStaticInfo(self, data, error, flag):
|
||||||
"""股票合约查询回报"""
|
"""股票合约查询回报"""
|
||||||
if not data:
|
if not data:
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -1226,8 +1229,8 @@ class SecTdApi(TdApi):
|
|||||||
|
|
||||||
contract.strikePrice = data['execPrice']
|
contract.strikePrice = data['execPrice']
|
||||||
|
|
||||||
contract.underlyingSymbol = data['securityID']
|
contract.underlyingSymbol = '-'.join([data['securityID'], str(data['endTradingDay'])[2:-2]])
|
||||||
contract.expiryDate = data['endTradingDay']
|
contract.expiryDate = str(data['endTradingDay'])
|
||||||
|
|
||||||
# 合约类型
|
# 合约类型
|
||||||
contract.productClass = PRODUCT_OPTION
|
contract.productClass = PRODUCT_OPTION
|
||||||
|
@ -277,6 +277,11 @@ class MainEngine(object):
|
|||||||
"""查询委托"""
|
"""查询委托"""
|
||||||
return self.dataEngine.getOrder(vtOrderID)
|
return self.dataEngine.getOrder(vtOrderID)
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
def getPositionDetail(self, vtSymbol):
|
||||||
|
"""查询持仓细节"""
|
||||||
|
return self.dataEngine.getPositionDetail(vtSymbol)
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
def getAllWorkingOrders(self):
|
def getAllWorkingOrders(self):
|
||||||
"""查询所有的活跃的委托(返回列表)"""
|
"""查询所有的活跃的委托(返回列表)"""
|
||||||
|
Loading…
Reference in New Issue
Block a user