更新
This commit is contained in:
parent
5bd718fa2e
commit
28152c2852
@ -741,6 +741,8 @@ class TradingWidget(QtWidgets.QFrame):
|
||||
EXCHANGE_CZCE,
|
||||
EXCHANGE_SSE,
|
||||
EXCHANGE_SZSE,
|
||||
EXCHANGE_XSHG,
|
||||
EXCHANGE_XSHE,
|
||||
EXCHANGE_INE,
|
||||
EXCHANGE_SGE,
|
||||
EXCHANGE_HKEX,
|
||||
@ -984,22 +986,27 @@ class TradingWidget(QtWidgets.QFrame):
|
||||
currency = self.comboCurrency.currentText()
|
||||
productClass = self.comboProductClass.currentText()
|
||||
gatewayName = self.comboGateway.currentText()
|
||||
|
||||
# 查询合约
|
||||
if exchange:
|
||||
vtSymbol = '.'.join([symbol, exchange])
|
||||
contract = self.mainEngine.getContract(vtSymbol)
|
||||
else:
|
||||
vtSymbol = symbol
|
||||
contract = self.mainEngine.getContract(symbol)
|
||||
|
||||
if contract:
|
||||
vtSymbol = contract.vtSymbol
|
||||
if len(gatewayName)==0 and len(contract.gatewayName) > 0:
|
||||
gatewayName = contract.gatewayName
|
||||
self.lineName.setText(contract.name)
|
||||
exchange = contract.exchange # 保证有交易所代码
|
||||
|
||||
|
||||
try:
|
||||
# 查询合约
|
||||
if exchange:
|
||||
vtSymbol = '.'.join([symbol, exchange])
|
||||
contract = self.mainEngine.getContract(vtSymbol)
|
||||
else:
|
||||
vtSymbol = symbol
|
||||
contract = self.mainEngine.getContract(symbol)
|
||||
|
||||
if contract:
|
||||
vtSymbol = contract.vtSymbol
|
||||
if len(gatewayName)==0 and contract.gatewayName is not None and len(contract.gatewayName) > 0:
|
||||
gatewayName = contract.gatewayName
|
||||
self.lineName.setText(contract.name)
|
||||
exchange = contract.exchange # 保证有交易所代码
|
||||
|
||||
except Exception as ex:
|
||||
print(u'获取合约{}异常:{},{}'.format(symbol,str(ex),traceback.format_exc()),file=sys.stderr)
|
||||
return
|
||||
|
||||
# 清空价格数量
|
||||
self.spinPrice.setValue(0)
|
||||
#self.spinVolume.setValue(0)
|
||||
@ -1103,6 +1110,8 @@ class TradingWidget(QtWidgets.QFrame):
|
||||
else:
|
||||
self.labelReturn.setText('')
|
||||
|
||||
self.comboExchange.setCurrentText(tick.exchange)
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
def connectSignal(self):
|
||||
"""连接Signal"""
|
||||
@ -1244,8 +1253,15 @@ class TradingWidget(QtWidgets.QFrame):
|
||||
return
|
||||
|
||||
if tick.vtSymbol:
|
||||
|
||||
# 更新交易组件的显示合约
|
||||
self.lineSymbol.setText(tick.vtSymbol)
|
||||
if '.' in tick.vtSymbol:
|
||||
symbol_pairs = tick.vtSymbol.split('.')
|
||||
if symbol_pairs[-1] != 'SPD':
|
||||
self.lineSymbol.setText(symbol_pairs[0])
|
||||
self.comboExchange.setCurrentText(symbol_pairs[-1])
|
||||
else:
|
||||
self.lineSymbol.setText(tick.vtSymbol)
|
||||
self.updateSymbol()
|
||||
|
||||
# 自动填写信息
|
||||
@ -1302,8 +1318,7 @@ class ContractMonitor(BasicMonitor):
|
||||
d = {'.'.join([contract.exchange, contract.symbol]):contract for contract in l}
|
||||
l2 = d.keys()
|
||||
#l2.sort(reverse=True)
|
||||
l2 = sorted(l2, reverse=True)
|
||||
|
||||
l2 = sorted(l2,reverse=True)
|
||||
self.setRowCount(len(l2))
|
||||
row = 0
|
||||
|
||||
@ -1358,7 +1373,7 @@ class ContractMonitor(BasicMonitor):
|
||||
class ContractManager(QtWidgets.QWidget):
|
||||
"""合约管理组件"""
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
#----------------------------------------------------------------------
|
||||
def __init__(self, mainEngine, parent=None):
|
||||
"""Constructor"""
|
||||
super(ContractManager, self).__init__(parent=parent)
|
||||
@ -1367,7 +1382,7 @@ class ContractManager(QtWidgets.QWidget):
|
||||
|
||||
self.initUi()
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
#----------------------------------------------------------------------
|
||||
def initUi(self):
|
||||
"""初始化界面"""
|
||||
self.setWindowTitle(vtText.CONTRACT_SEARCH)
|
||||
@ -1426,6 +1441,7 @@ class WorkingOrderMonitor(OrderMonitor):
|
||||
row = self.row(cell)
|
||||
self.hideRow(row)
|
||||
|
||||
|
||||
########################################################################
|
||||
class SettingEditor(QtWidgets.QWidget):
|
||||
"""配置编辑器"""
|
||||
|
@ -348,14 +348,15 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||
|
||||
return openAppFunction
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# ----------------------------------------------------------------------
|
||||
def test(self):
|
||||
"""测试按钮用的函数"""
|
||||
# 有需要使用手动触发的测试函数可以写在这里
|
||||
self.mainEngine.qryStatus()
|
||||
self.mainEngine.saveData()
|
||||
pass
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# ----------------------------------------------------------------------
|
||||
def openAbout(self):
|
||||
"""打开关于"""
|
||||
try:
|
||||
@ -424,7 +425,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||
except:
|
||||
pass
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# ----------------------------------------------------------------------
|
||||
def closeEvent(self, event):
|
||||
"""关闭事件"""
|
||||
reply = QtWidgets.QMessageBox.question(self, vtText.EXIT,
|
||||
@ -441,7 +442,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||
else:
|
||||
event.ignore()
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# ----------------------------------------------------------------------
|
||||
def createDock(self, widgetClass, widgetName, widgetArea):
|
||||
"""创建停靠组件"""
|
||||
widget = widgetClass(self.mainEngine, self.eventEngine)
|
||||
@ -459,7 +460,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||
settings.setValue('state', self.saveState())
|
||||
settings.setValue('geometry', self.saveGeometry())
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# ----------------------------------------------------------------------
|
||||
def loadWindowSettings(self, settingName):
|
||||
"""载入窗口设置"""
|
||||
settings = QtCore.QSettings('vn.trader', settingName)
|
||||
|
@ -6,6 +6,9 @@ import sys
|
||||
import platform
|
||||
import psutil
|
||||
|
||||
# changelog
|
||||
# 记录gpid,修改为pid
|
||||
|
||||
run_path = os.path.abspath(os.path.join(os.getcwd(), 'logs'))
|
||||
if not os.path.isdir(run_path):
|
||||
os.mkdir(run_path)
|
||||
@ -68,19 +71,23 @@ if _status():
|
||||
print( u'another service is already running...')
|
||||
exit(0)
|
||||
|
||||
def _save_gpid():
|
||||
def _save_gpid(log=True):
|
||||
|
||||
plat = str(platform.system())
|
||||
if plat == 'Windows':
|
||||
gpid = os.getpid()
|
||||
else: # unix
|
||||
gpid = os.getpgrp() if USE_GPID else os.getpid()
|
||||
print( 'gpid={}'.format(gpid))
|
||||
if log:
|
||||
print( 'gpid={}'.format(gpid))
|
||||
|
||||
with open(gpid_file, 'w') as f:
|
||||
f.write(str(gpid))
|
||||
if log:
|
||||
print(u'wrote gpid file:{}'.format(gpid_file))
|
||||
|
||||
print(u'wrote gpid file:{}'.format(gpid_file))
|
||||
def update_gpid():
|
||||
_save_gpid(log=False)
|
||||
|
||||
_save_gpid()
|
||||
|
||||
|
@ -274,6 +274,7 @@ class PositionMonitor(BasicMonitor):
|
||||
d['ydPosition'] = {'chinese': u'昨持仓', 'cellType': ""}
|
||||
d['frozen'] = {'chinese': u'冻结量', 'cellType': ""}
|
||||
d['price'] = {'chinese': u'价格', 'cellType': ""}
|
||||
d['positionProfit'] = {'chinese': u'持仓盈亏', 'cellType': ""}
|
||||
d['gatewayName'] = {'chinese': u'接口', 'cellType': ""}
|
||||
self.setHeaderDict(d)
|
||||
self.createLogger(EVENT_POSITION)
|
||||
|
@ -176,10 +176,45 @@ class ClientEngine(object):
|
||||
self.client.initStrategy(name, force=force)
|
||||
|
||||
def startStrategy(self,name):
|
||||
self.client.startStrategy(name)
|
||||
if hasattr(self.client,'startStrategy'):
|
||||
self.writeLog(u'启动服务端策略:{}'.format(name))
|
||||
self.client.startStrategy(name)
|
||||
else:
|
||||
self.writeLog(u'RPC客户端没有startStrategy得方法')
|
||||
print(u'RPC客户端没有startStrategy得方法',file=sys.stderr)
|
||||
|
||||
def stopStrategy(self,name):
|
||||
self.client.stopStrategy(name)
|
||||
if hasattr(self.client,'stopStrategy'):
|
||||
self.writeLog(u'停止运行服务端策略:{}'.format(name))
|
||||
self.client.stopStrategy(name)
|
||||
else:
|
||||
self.writeLog(u'RPC客户端没有stopStrategy得方法')
|
||||
print(u'RPC客户端没有stopStrategy得方法',file=sys.stderr)
|
||||
|
||||
def removeStrategy(self,name):
|
||||
if hasattr(self.client,'removeStrategy'):
|
||||
self.writeLog(u'移除服务端策略:{}'.format(name))
|
||||
self.client.removeStrategy(name)
|
||||
else:
|
||||
self.writeLog(u'RPC客户端没有removeStrategy得方法')
|
||||
print(u'RPC客户端没有removeStrategy得方法',file=sys.stderr)
|
||||
|
||||
def addStrategy(self,cta_setting):
|
||||
if hasattr(self.client,'addStrategy'):
|
||||
self.writeLog(u'添加服务端策略:{}'.format(cta_setting.get('name')))
|
||||
self.client.addStrategy(cta_setting)
|
||||
else:
|
||||
self.writeLog(u'RPC客户端没有addStrategy的方法')
|
||||
print(u'RPC客户端没有addStrategy的方法', file=sys.stderr)
|
||||
|
||||
def forceClosePos(self,name):
|
||||
if hasattr(self.client,'forceClosePos'):
|
||||
self.writeLog(u'调用服务端策略强制清除仓位:{}'.format(name))
|
||||
self.client.forceClosePos(name)
|
||||
else:
|
||||
self.writeLog(u'RPC客户端没有forceClosePos得方法')
|
||||
print(u'RPC客户端没有forceClosePos得方法', file=sys.stderr)
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
def main():
|
||||
"""客户端主程序入口"""
|
||||
|
@ -101,13 +101,13 @@ def roundToVolumeTick(volumeTick,volume):
|
||||
if volumeTick == 0:
|
||||
return volume
|
||||
# 取整
|
||||
newVolume = volume - volume % volumeTick
|
||||
newVolume = round(volume / volumeTick, 0) * volumeTick
|
||||
|
||||
if isinstance(volumeTick,float):
|
||||
v_exponent = decimal.Decimal(str(newVolume))
|
||||
v_exponent = decimal.Decimal(str(volume))
|
||||
vt_exponent = decimal.Decimal(str(volumeTick))
|
||||
if abs(v_exponent.as_tuple().exponent) > abs(vt_exponent.as_tuple().exponent):
|
||||
newVolume = round(newVolume, ndigits=abs(vt_exponent.as_tuple().exponent))
|
||||
newVolume = round(volume, ndigits=abs(vt_exponent.as_tuple().exponent))
|
||||
newVolume = float(str(newVolume))
|
||||
|
||||
return newVolume
|
||||
|
@ -36,7 +36,7 @@ class VtGateway(object):
|
||||
event1.dict_['data'] = tick
|
||||
self.eventEngine.put(event1)
|
||||
|
||||
if tick.lastPrice is not None or tick.lastPrice != 0:
|
||||
if tick.lastPrice is not None and tick.lastPrice != 0:
|
||||
self.symbol_price_dict.update({tick.vtSymbol: tick.lastPrice})
|
||||
elif tick.askPrice1 is not None and tick.bidPrice1 is not None:
|
||||
self.symbol_price_dict.update({tick.vtSymbol: (tick.askPrice1 + tick.bidPrice1)/2})
|
||||
@ -147,7 +147,7 @@ class VtGateway(object):
|
||||
|
||||
filename = os.path.abspath(os.path.join(path, 'Gateway'))
|
||||
|
||||
print(u'create logger:{}'.format(filename))
|
||||
#print(u'create logger:{}'.format(filename))
|
||||
self.logger = setup_logger(filename=filename, name='vtGateway', debug=True)
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
|
@ -5,7 +5,10 @@ from datetime import datetime
|
||||
|
||||
|
||||
from vnpy.trader.vtConstant import (EMPTY_STRING, EMPTY_UNICODE,
|
||||
EMPTY_FLOAT, EMPTY_INT)
|
||||
EMPTY_FLOAT, EMPTY_INT, DIRECTION_LONG, DIRECTION_SHORT,
|
||||
OFFSET_OPEN, OFFSET_CLOSE,
|
||||
OFFSET_CLOSETODAY, OFFSET_CLOSEYESTERDAY)
|
||||
|
||||
from vnpy.trader.language import constant
|
||||
|
||||
########################################################################
|
||||
@ -40,7 +43,7 @@ class VtTickData(VtBaseData):
|
||||
self.preOpenInterest = EMPTY_INT # 昨持仓量
|
||||
self.openInterest = EMPTY_INT # 持仓量
|
||||
self.time = EMPTY_STRING # 时间 11:20:56.5
|
||||
self.date = EMPTY_STRING # 日期 20151009
|
||||
self.date = EMPTY_STRING # 日期 2015-10-09
|
||||
self.tradingDay = EMPTY_STRING # 交易日期
|
||||
|
||||
# 常规行情
|
||||
@ -96,7 +99,7 @@ class VtTickData(VtBaseData):
|
||||
tick.lastVolume = lastVolume
|
||||
tick.openInterest = openInterest
|
||||
tick.datetime = datetime.now()
|
||||
tick.date = tick.datetime.strftime('%Y%m%d')
|
||||
tick.date = tick.datetime.strftime('%Y-%m-%d')
|
||||
tick.time = tick.datetime.strftime('%H:%M:%S')
|
||||
|
||||
tick.openPrice = openPrice
|
||||
@ -158,6 +161,9 @@ class VtTradeData(VtBaseData):
|
||||
self.price = EMPTY_FLOAT # 成交价格
|
||||
self.volume = EMPTY_FLOAT # 成交数量
|
||||
self.tradeTime = EMPTY_STRING # 成交时间
|
||||
self.dt = None # 成交时间(datetime类型)
|
||||
|
||||
self.strategy = EMPTY_STRING # 策略实例名
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
@staticmethod
|
||||
@ -473,6 +479,8 @@ class VtSubscribeReq(object):
|
||||
self.symbol = EMPTY_STRING # 代码
|
||||
self.exchange = EMPTY_STRING # 交易所
|
||||
|
||||
self.is_bar = False # True:订阅1分钟bar行情;False:订阅tick行情,
|
||||
|
||||
# 以下为IB相关
|
||||
self.productClass = EMPTY_UNICODE # 合约类型
|
||||
self.currency = EMPTY_STRING # 合约货币
|
||||
@ -556,3 +564,124 @@ class VtSingleton(type):
|
||||
cls._instances[cls] = super(VtSingleton, cls).__call__(*args, **kwargs)
|
||||
|
||||
return cls._instances[cls]
|
||||
|
||||
|
||||
########################################################################
|
||||
class PositionBuffer(object):
|
||||
"""持仓缓存信息(本地维护的持仓数据)"""
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
def __init__(self):
|
||||
"""Constructor"""
|
||||
self.vtSymbol = EMPTY_STRING
|
||||
|
||||
# 多头
|
||||
self.longPosition = EMPTY_INT
|
||||
self.longToday = EMPTY_INT
|
||||
self.longYd = EMPTY_INT
|
||||
|
||||
self.longPrice = EMPTY_FLOAT
|
||||
self.longProfit = EMPTY_FLOAT
|
||||
self.longFrozen = EMPTY_FLOAT
|
||||
|
||||
# 空头
|
||||
self.shortPosition = EMPTY_INT
|
||||
self.shortToday = EMPTY_INT
|
||||
self.shortYd = EMPTY_INT
|
||||
|
||||
self.shortPrice = EMPTY_FLOAT
|
||||
self.shortProfit = EMPTY_FLOAT
|
||||
|
||||
self.shortFrozen = EMPTY_FLOAT
|
||||
|
||||
self.frozen = EMPTY_FLOAT
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
def toStr(self):
|
||||
"""更新显示信息"""
|
||||
str = u'long:{},yd:{},td:{}, short:{},yd:{},td:{}, fz:{};' \
|
||||
.format(self.longPosition, self.longYd, self.longToday,
|
||||
self.shortPosition, self.shortYd, self.shortToday, self.frozen)
|
||||
return str
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
def updatePositionData(self, pos):
|
||||
"""更新持仓数据"""
|
||||
if pos.direction == DIRECTION_SHORT:
|
||||
self.shortPosition = pos.position # >=0
|
||||
self.shortYd = pos.ydPosition # >=0
|
||||
self.shortToday = self.shortPosition - self.shortYd # >=0
|
||||
|
||||
self.shortPrice = pos.price
|
||||
self.shortProfit = pos.positionProfit
|
||||
self.shortFrozen = pos.frozen
|
||||
|
||||
else:
|
||||
self.longPosition = pos.position # >=0
|
||||
self.longYd = pos.ydPosition # >=0
|
||||
self.longToday = self.longPosition - self.longYd # >=0
|
||||
|
||||
self.longPrice = pos.price
|
||||
self.longProfit = pos.positionProfit
|
||||
self.longFrozen = pos.frozen
|
||||
|
||||
self.frozen = self.shortFrozen + self.longFrozen
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
def updateTradeData(self, trade):
|
||||
"""更新成交数据"""
|
||||
|
||||
if trade.direction == DIRECTION_SHORT:
|
||||
# 空头和多头相同
|
||||
if trade.offset == OFFSET_OPEN: # 开仓
|
||||
self.shortPosition += trade.volume
|
||||
self.shortToday += trade.volume # 增加的是今仓
|
||||
|
||||
elif trade.offset == OFFSET_CLOSETODAY: # 平今
|
||||
self.longPosition -= trade.volume
|
||||
self.longToday -= trade.volume # 减少今仓
|
||||
|
||||
elif trade.offset == OFFSET_CLOSEYESTERDAY: # 平昨
|
||||
self.longPosition -= trade.volume
|
||||
self.longYd -= trade.volume # 减少昨仓
|
||||
|
||||
else: # 平仓
|
||||
self.longPosition -= trade.volume
|
||||
self.longToday -= trade.volume # 优先减今仓
|
||||
if self.longToday < 0:
|
||||
self.longYd += self.longToday
|
||||
self.longToday = 0
|
||||
|
||||
if self.longPosition <= 0:
|
||||
self.longPosition = 0
|
||||
if self.longToday <= 0:
|
||||
self.longToday = 0
|
||||
if self.longYd <= 0:
|
||||
self.longYd = 0
|
||||
else:
|
||||
# 多方开仓,则对应多头的持仓和今仓增加
|
||||
if trade.offset == OFFSET_OPEN:
|
||||
self.longPosition += trade.volume
|
||||
self.longToday += trade.volume
|
||||
# 多方平今,对应空头的持仓和今仓减少
|
||||
elif trade.offset == OFFSET_CLOSETODAY:
|
||||
self.shortPosition -= trade.volume
|
||||
self.shortToday -= trade.volume
|
||||
|
||||
elif trade.offset == OFFSET_CLOSEYESTERDAY:
|
||||
self.shortPosition -= trade.volume
|
||||
self.shortYd -= trade.volume
|
||||
else:
|
||||
self.shortPosition -= trade.volume
|
||||
self.shortToday -= trade.volume
|
||||
if self.shortToday <= 0:
|
||||
self.shortYd += self.shortToday
|
||||
self.shortToday = 0
|
||||
|
||||
if self.shortPosition <= 0:
|
||||
self.shortPosition = 0
|
||||
if self.shortToday <= 0:
|
||||
self.shortToday = 0
|
||||
if self.shortYd <= 0:
|
||||
self.shortYd = 0
|
||||
# 多方平昨,对应空头的持仓和昨仓减少
|
Loading…
Reference in New Issue
Block a user