Skip to content

Commit

Permalink
Merge pull request #82 from xingetouzi/spotOrderTemplate-trading
Browse files Browse the repository at this point in the history
Spot order template trading
  • Loading branch information
tianrq10 authored Apr 13, 2019
2 parents c5f7fc9 + 22cff42 commit 834cfc1
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 27 deletions.
13 changes: 7 additions & 6 deletions vnpy/trader/app/ctaStrategy/ctaBacktesting.py
Original file line number Diff line number Diff line change
Expand Up @@ -260,12 +260,13 @@ def loadHistoryData(self, symbolList, startDate, endDate=None, dataMode=None):
self.output(f"{symbol}: 从本地缓存文件实取{acq}, 最大应取{need}, 还需从数据库取{need-acq}")

# 如果没有完全从本地文件加载完数据, 则尝试从指定的mongodb下载数据, 并缓存到本地
if self.dbURI:
dbName = None
if dataMode == self.BAR_MODE:
dbName = self.bardbName
else:
dbName = self.tickdbName
if self.dbURI and dbName is not None: # 有设置从指定数据库和表取数据
import pymongo
if dataMode == self.BAR_MODE:
dbName = self.bardbName
else:
dbName = self.tickdbName
self.dbClient = pymongo.MongoClient(self.dbURI)[dbName]
for symbol, need_datetimes in symbols_no_data.items():
if len(need_datetimes) > 0: # 需要从数据库取数据
Expand Down Expand Up @@ -300,7 +301,7 @@ def loadHistoryData(self, symbolList, startDate, endDate=None, dataMode=None):
self.output("数据库没有 %s 这个品种" % symbol)
self.output("这些品种在我们的数据库里: %s" % self.dbClient.collection_names())
else:
self.output('没有设置回测数据库URI, 无法回补缓存数据。请在回测设置 engine.setDB_URI("mongodb://localhost:27017")')
self.output('没有设置回测数据库相关信息, 无法回补缓存数据。请在回测入口设置 engine.setDB_URI 和 engine.setDatabase')

if len(dataList) > 0:
dataList.sort(key=lambda x: x.datetime)
Expand Down
11 changes: 5 additions & 6 deletions vnpy/trader/gateway/okexGateway/spot.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
# 方向和开平映射
typeMap = {}
typeMap[(DIRECTION_LONG, OFFSET_OPEN)] = 'buy'
typeMap[(DIRECTION_LONG, OFFSET_CLOSE)] = 'buy'
typeMap[(DIRECTION_SHORT, OFFSET_OPEN)] = 'sell'
typeMap[(DIRECTION_SHORT, OFFSET_CLOSE)] = 'sell'
typeMapReverse = {v:k for k,v in typeMap.items()}

Expand Down Expand Up @@ -740,9 +742,7 @@ def onSpotTick(self, d):
tick.volume = float(data['quote_volume_24h'])
tick.askPrice1 = float(data['best_ask'])
tick.bidPrice1 = float(data['best_bid'])
tick.datetime = datetime.strptime(data['timestamp'], ISO_DATETIME_FORMAT)
tick.date = tick.datetime.strftime('%Y%m%d')
tick.time = tick.datetime.strftime('%H:%M:%S.%f')
tick.datetime, tick.date, tick.time = self.gateway.convertDatetime(data['timestamp'])
tick.localTime = datetime.now()
tick.volumeChange = 0
tick.lastVolume = 0
Expand Down Expand Up @@ -772,9 +772,7 @@ def onSpotDepth(self, d):
tick.__setattr__(f'bidPrice{(idx + 1)}', float(price))
tick.__setattr__(f'bidVolume{(idx + 1)}', float(volume))

tick.datetime = datetime.strptime(data['timestamp'], ISO_DATETIME_FORMAT)
tick.date = tick.datetime.strftime('%Y%m%d')
tick.time = tick.datetime.strftime('%H:%M:%S.%f')
tick.datetime, tick.date, tick.time = self.gateway.convertDatetime(data['timestamp'])
tick.localTime = datetime.now()
tick.volumeChange = 0
tick.lastVolume = 0
Expand All @@ -792,6 +790,7 @@ def onSpotTrades(self,d):
tick.lastTradedTime = data['timestamp']
tick.type = data['side']
tick.volumeChange = 1
tick.datetime, tick.date, tick.time = self.gateway.convertDatetime(data['timestamp'])
tick.localTime = datetime.now()
if tick.askPrice1:
tick=copy(tick)
Expand Down
15 changes: 12 additions & 3 deletions vnpy/trader/utils/templates/Readme.MD
Original file line number Diff line number Diff line change
Expand Up @@ -410,13 +410,17 @@ OrderPack.info 用于记录自定义信息,但是有一些字段已被占用
|price|float|限制价格。|
|volume|float|下单数。|
|expire|float|存在时间,秒数|
|vtOrderIDs|set|与该信息绑定的订单号|
|vtOrderIDs|set|与该信息绑定的未结束的订单号|
|closedOrderIDs|set|结束/有成交的订单号|
|inValidOrderIDs|set|结束/无成交的订单号|


### 构造方法

**`
TimeLimitOrderInfo.__init__(vtSymbol, orderType, volume, price, expire)
`**

|name|type|description|
|:-|:-|:-|
|orderType|str|发单类型,支持ctaBase.CTAORDER_BUY, ctaBase.CTAORDER_COVER, ctaBase.CTAORDER_SELL, ctaBase.CTAORDER_SHORT。|
Expand All @@ -434,11 +438,16 @@ TimeLimitOrderInfo.__init__(vtSymbol, orderType, volume, price, expire)

基础属性继承自TimeLimitOrderInfo

额外属性:

|name|type|description|
|:-|:-|:-|
|TYPE|str: "_ComposoryOrderInfo"|强制单单标记字段|
|orderType|str|发单类型,支持ctaBase.CTAORDER_BUY, ctaBase.CTAORDER_COVER, ctaBase.CTAORDER_SELL, ctaBase.CTAORDER_SHORT。|
|vtSymbol|str|品种名。|
|volume|float|下单数。|
|expire|float|存在时间,秒数|
|vtOrderIDs|set|与该信息绑定的未结束的订单号|
|closedOrderIDs|set|结束/有成交的订单号|
|inValidOrderIDs|set|结束/无成交的订单号|


## `class` AutoExitInfo
Expand Down
21 changes: 11 additions & 10 deletions vnpy/trader/utils/templates/orderTemplate.py
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,8 @@ def onOrder(self, order):
else:
if op.info.get(self._FINISH_TAG, False):
return
if order.status in STATUS_FINISHED:
op.info[self._FINISH_TAG] = True
op.order = order

for name in op.tracks:
Expand All @@ -400,10 +402,6 @@ def onOrder(self, order):

self.onOrderPack(op)

if op.order.status in STATUS_FINISHED:
op.info[self._FINISH_TAG] = True


def onOrderPack(self, op):
pass

Expand All @@ -418,9 +416,10 @@ def _round(self, value):

def makeOrder(self, orderType, vtSymbol, price, volume, priceType=constant.PRICETYPE_LIMITPRICE, stop=False, **info):
volume = self._round(volume)
assert volume > 0
assert volume > 0, volume

price = self.adjustPrice(vtSymbol, price, "send order")
assert price > 0
assert price > 0, price
vtOrderIDList = self.sendOrder(orderType, vtSymbol, price, volume, priceType, stop)
logging.debug("%s | makeOrder: %s, %s, %s, %s | into: %s", self.currentTime, orderType, vtSymbol, price, volume, info)

Expand Down Expand Up @@ -707,9 +706,11 @@ def checkTimeLimitOrders(self):
if not tlo.vtOrderIDs:
pool.pop(id(tlo))

def checkComposoryOrders(self):
def checkComposoryOrders(self, vtSymbol):
pool = self._infoPool[ComposoryOrderInfo.TYPE]
for cpo in list(pool.values()):
if cpo.vtSymbol != vtSymbol:
continue
for op in self.iterValidOrderPacks(*cpo.vtOrderIDs):
self.onComposoryOrder(op, True)
if not cpo.vtOrderIDs:
Expand Down Expand Up @@ -1041,15 +1042,15 @@ def currentTime(self):
def getExecPrice(self, vtSymbol, orderType):
if orderType in self._ORDERTYPE_LONG:
if vtSymbol in self._tickInstance:
return self._tickInstance[vtSymbol].upperLimit*0.99
return self._tickInstance[vtSymbol].lastPrice * 1.02
elif vtSymbol in self._barInstance:
return self._barInstance[vtSymbol].high
else:
return None

elif orderType in self._ORDERTYPE_SHORT:
if vtSymbol in self._tickInstance:
return self._tickInstance[vtSymbol].lowerLimit*1.01
return self._tickInstance[vtSymbol].lastPrice * 0.98
elif vtSymbol in self._barInstance:
return self._barInstance[vtSymbol].low
else:
Expand Down Expand Up @@ -1154,7 +1155,7 @@ def onJoinOrderChild(self, op):
self.onOrder(parent.order)

def checkOnPeriodStart(self, bar):
self.checkComposoryOrders()
self.checkComposoryOrders(bar.vtSymbol)
self.checkTimeLimitOrders()
self.checkAutoExit(bar.vtSymbol)
self.checkConditionalClose()
Expand Down
14 changes: 12 additions & 2 deletions vnpy/trader/utils/templates/spotOrderTemplate.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from vnpy.trader.utils.templates.orderTemplate import OrderTemplate, DIRECTION_MAP, ctaBase, constant
from vnpy.trader.utils.templates.orderTemplate import OrderTemplate, DIRECTION_MAP, ctaBase, constant, STATUS_FINISHED, showOrder
import numpy as np


Expand All @@ -15,6 +15,8 @@ class SpotOrderTemplate(OrderTemplate):

_MAXIMUM_VOLUME_ADJUST = 1

_ORIGIN_TRADED_VOLUME = "_ORIGIN_TRADED_VOLUME"

def maximumOrderVolume(self, vtSymbol, orderType, price=None):
if self.getEngineType() != ctaBase.ENGINETYPE_TRADING:
return np.inf
Expand Down Expand Up @@ -47,4 +49,12 @@ def adjustVolume(self, vtSymbol, volume):
if contract.minVolume:
return int(volume/contract.minVolume) * contract.minVolume
else:
return volume
return volume

def composoryClose(self, op, expire=None, volume=None):
if volume:
if op.order.status not in STATUS_FINISHED:
raise ValueError("Order not finished: %s" % showOrder(op.order, "vtOrderID", "status", "tradedVolume"))
op.order.tradedVolume = volume
op.info[self._ORIGIN_TRADED_VOLUME] = op.order.tradedVolume
return super().composoryClose(op, expire)

0 comments on commit 834cfc1

Please sign in to comment.