[增强] linux下ctp*.so, gw bug fix, float显示截短

This commit is contained in:
msincenselee 2020-03-27 21:39:30 +08:00
parent aa09f30f06
commit db6e107b95
21 changed files with 126 additions and 177 deletions

BIN
vnpy/api/ctp/vnctpmd.so Normal file

Binary file not shown.

BIN
vnpy/api/ctp/vnctptd.so Normal file

Binary file not shown.

View File

@ -65,6 +65,7 @@ from vnpy.trader.util_logger import setup_logger
from vnpy.data.mongo.mongo_data import MongoData
from uuid import uuid1
class BackTestingEngine(object):
"""
CTA回测引擎
@ -1680,7 +1681,8 @@ class BackTestingEngine(object):
if len(self.short_position_list) > 0:
for t in self.short_position_list:
# 当前空单保证金
cur_occupy_money = max(self.get_price(t.vt_symbol), t.price) * abs(t.volume) * self.get_margin_rate(t.vt_symbol)
cur_occupy_money = max(self.get_price(t.vt_symbol), t.price) * abs(t.volume) * self.get_margin_rate(
t.vt_symbol)
# 该合约短号的累计空单保证金
underly_symbol = get_underlying_symbol(t.symbol)
@ -1695,7 +1697,8 @@ class BackTestingEngine(object):
# 计算多空的保证金累加(对锁的取最大值)
for underly_symbol in occupy_underly_symbol_set:
occupy_money += occupy_long_money_dict.get(underly_symbol, 0) + occupy_short_money_dict.get(underly_symbol, 0)
occupy_money += occupy_long_money_dict.get(underly_symbol, 0) + occupy_short_money_dict.get(underly_symbol,
0)
# 可用资金 = 当前净值 - 占用保证金
self.avaliable = self.net_capital - occupy_money

View File

@ -344,7 +344,6 @@ class CtaEngine(BaseEngine):
holding = self.get_position_holding(position.vt_symbol, position.gateway_name)
holding.update_position(position)
def check_unsubscribed_symbols(self):
"""检查未订阅合约"""
@ -1179,7 +1178,7 @@ class CtaEngine(BaseEngine):
self.write_log(msg)
return True, msg
def save_strategy_data(self, select_name: str):
def save_strategy_data(self, select_name: str = 'ALL'):
""" save strategy data"""
has_executed = False
msg = ""
@ -1215,7 +1214,7 @@ class CtaEngine(BaseEngine):
self.write_error(u'保存策略{}数据异常:'.format(strategy_name, str(ex)))
self.write_error(traceback.format_exc())
def save_strategy_snapshot(self, select_name: str):
def save_strategy_snapshot(self, select_name: str = 'ALL'):
"""
保存策略K线切片数据
:param select_name:
@ -1607,7 +1606,7 @@ class CtaEngine(BaseEngine):
try:
from vnpy.trader.util_wechat import send_wx_msg
send_wx_msg(content=msg)
except Exception as ex:
except Exception: # noqa
pass
ret_msg = u'持仓不匹配: {}' \
.format(pos_compare_result)

View File

@ -13,9 +13,6 @@ import gc
import pandas as pd
import traceback
import random
import bz2
import pickle
from datetime import datetime, timedelta
from time import sleep
@ -196,7 +193,6 @@ class PortfolioTestingEngine(BackTestingEngine):
symbol, exchange = extract_vt_symbol(vt_symbol)
self.load_bar_csv_to_df(vt_symbol, self.bar_csv_file.get(symbol))
# 合并数据
self.comine_bar_df()
@ -309,6 +305,7 @@ class PortfolioTestingEngine(BackTestingEngine):
traceback.print_exc()
return
def single_test(test_setting: dict, strategy_setting: dict):
"""
单一回测

View File

@ -16,11 +16,9 @@ from vnpy.trader.constant import Interval, Direction, Offset, Status, OrderType
from vnpy.trader.object import BarData, TickData, OrderData, TradeData
from vnpy.trader.utility import virtual, append_data, extract_vt_symbol, get_underlying_symbol
from .base import StopOrder, EngineType
from vnpy.component.cta_grid_trade import CtaGrid, CtaGridTrade, LOCK_GRID
from .base import StopOrder
from vnpy.component.cta_grid_trade import CtaGrid, CtaGridTrade
from vnpy.component.cta_position import CtaPosition
from vnpy.component.cta_policy import CtaPolicy # noqa
class CtaTemplate(ABC):
"""CTA策略模板"""
@ -416,8 +414,6 @@ class CtaTemplate(ABC):
self.cta_engine.sync_strategy_data(self)
class CtaFutureTemplate(CtaTemplate):
"""
合约期货模板
@ -844,37 +840,7 @@ class CtaFutureTemplate(CtaTemplate):
self.active_orders.pop(order.vt_orderid, None)
return
order_price = old_order['price']
order_type = old_order.get('order_type', OrderType.LIMIT)
order_retry = old_order.get('retry', 0)
grid = old_order.get('grid', None)
if order_retry > 20:
# 这里超过20次尝试失败后不再尝试,发出告警信息
msg = u'{} {}/{}手, 重试开仓次数{}>20' \
.format(self.strategy_name,
order_vt_symbol,
order_volume,
order_retry)
self.write_error(msg)
self.send_wechat(msg)
if grid:
if order.vt_orderid in grid.order_ids:
grid.order_ids.remove(order.vt_orderid)
# 网格的所有委托单已经执行完毕
if len(grid.order_ids) == 0:
grid.order_status = False
self.gt.save()
self.write_log(u'网格信息更新:{}'.format(grid.__dict__))
self.write_log(u'移除:{}'.format(order.vt_orderid))
self.active_orders.pop(order.vt_orderid, None)
return
order_retry += 1
pre_status = old_order.get('status', Status.NOTTRADED)
old_order.update({'status': Status.CANCELLED})
self.write_log(u'委托单状态:{}=>{}'.format(pre_status, old_order.get('status')))
@ -918,29 +884,7 @@ class CtaFutureTemplate(CtaTemplate):
self.active_orders.pop(order.vt_orderid, None)
return
order_price = old_order['price']
order_type = old_order.get('order_type', OrderType.LIMIT)
order_retry = old_order.get('retry', 1)
grid = old_order.get('grid', None)
if order_retry > 20:
msg = u'{} 平仓撤单 {}/{}手, 重试平仓次数{}>20' \
.format(self.strategy_name, order_symbol, order_volume, order_retry)
self.write_error(msg)
self.send_wechat(msg)
if grid:
if order.vt_orderid in grid.order_ids:
grid.order_ids.remove(order.vt_orderid)
if not grid.order_ids:
grid.order_status = False
self.gt.save()
self.write_log(u'更新网格=>{}'.format(grid.__dict__))
self.write_log(u'移除活动订单:{}'.format(order.vt_orderid))
self.active_orders.pop(order.vt_orderid, None)
return
order_retry += 1
pre_status = old_order.get('status', Status.NOTTRADED)
old_order.update({'status': Status.CANCELLED})
self.write_log(u'委托单状态:{}=>{}'.format(pre_status, old_order.get('status')))
@ -957,7 +901,6 @@ class CtaFutureTemplate(CtaTemplate):
def on_stop_order(self, stop_order: StopOrder):
self.write_log(f'停止单触发:{stop_order.__dict__}')
def grid_check_stop(self):
"""
网格逐一止损/止盈检查 (根据指数价格进行止损止盈
@ -1022,7 +965,6 @@ class CtaFutureTemplate(CtaTemplate):
.format(grid.type, grid.open_price, grid.volume, grid.close_price))
return False
def grid_short(self, grid):
"""
事务开空仓
@ -1302,7 +1244,6 @@ class CtaFutureTemplate(CtaTemplate):
if len(self.active_orders) == 0:
self.entrust = 0
def display_grids(self):
"""更新网格显示信息"""
if not self.inited:
@ -1340,7 +1281,9 @@ class CtaFutureTemplate(CtaTemplate):
save_path = self.cta_engine.get_data_path()
try:
if 'margin' not in dist_data:
dist_data.update({'margin': dist_data.get('price', 0) * dist_data.get('volume', 0) * self.cta_engine.get_margin_rate(dist_data.get('symbol', self.vt_symbol))})
dist_data.update({'margin': dist_data.get('price', 0) * dist_data.get('volume',
0) * self.cta_engine.get_margin_rate(
dist_data.get('symbol', self.vt_symbol))})
if self.position and 'long_pos' not in dist_data:
dist_data.update({'long_pos': self.position.long_pos})
if self.position and 'short_pos' not in dist_data:
@ -1373,5 +1316,3 @@ class CtaFutureTemplate(CtaTemplate):
if self.backtesting:
return
self.cta_engine.send_wechat(msg=msg, strategy=self)

View File

@ -14,7 +14,11 @@ from .template import (
BarData,
TradeData,
OrderData,
CtaTemplate, CtaSignal, TargetPosTemplate, CtaProTemplate, CtaProFutureTemplate) # noqa
CtaTemplate,
CtaSignal,
TargetPosTemplate,
CtaProTemplate,
CtaProFutureTemplate) # noqa
from vnpy.trader.utility import BarGenerator, ArrayManager # noqa
from .template_spread import CtaSpreadTemplate

View File

@ -715,7 +715,9 @@ class CtaEngine(BaseEngine):
strategy = self.strategies.get(strategy_name, None)
if not strategy:
return False
if len(vt_symbol) == 0:
self.write_error(f'不能为{strategy_name}订阅空白合约')
return False
contract = self.main_engine.get_contract(vt_symbol)
if contract:
if contract.gateway_name and not gateway_name:
@ -1101,7 +1103,7 @@ class CtaEngine(BaseEngine):
self.write_log(msg)
return True, msg
def save_strategy_data(self, select_name: str):
def save_strategy_data(self, select_name: str = 'ALL'):
""" save strategy data"""
has_executed = False
msg = ""
@ -1137,7 +1139,7 @@ class CtaEngine(BaseEngine):
self.write_error(u'保存策略{}数据异常:'.format(strategy_name, str(ex)))
self.write_error(traceback.format_exc())
def save_strategy_snapshot(self, select_name: str):
def save_strategy_snapshot(self, select_name: str = 'ALL'):
"""
保存策略K线切片数据
:param select_name:
@ -1571,7 +1573,7 @@ class CtaEngine(BaseEngine):
try:
from vnpy.trader.util_wechat import send_wx_msg
send_wx_msg(content=msg)
except Exception as ex:
except Exception as ex: # noqa
pass
ret_msg = u'持仓不匹配: {}' \
.format(pos_compare_result)

View File

@ -1568,7 +1568,8 @@ class CtaProFutureTemplate(CtaProTemplate):
over_seconds = (dt - order_time).total_seconds()
# 只处理未成交的限价委托单
if order_status in [Status.NOTTRADED,Status.SUBMITTING] and (order_type == OrderType.LIMIT or '.SPD' in order_vt_symbol):
if order_status in [Status.NOTTRADED, Status.SUBMITTING] and (
order_type == OrderType.LIMIT or '.SPD' in order_vt_symbol):
if over_seconds > self.cancel_seconds or force: # 超过设置的时间还未成交
self.write_log(u'超时{}秒未成交取消委托单vt_orderid:{},order:{}'
.format(over_seconds, vt_orderid, order_info))

View File

@ -3353,10 +3353,10 @@ class CtaLineBar(object):
# 记录所有SK的顶部和底部
# 峰(顶部)
if self.line_sk[-1] < self.line_sk[-2] and self.line_sk[-3] < self.line_sk[-2]:
t = {}
t = dict()
t['type'] = u'T'
t['sk'] = self.line_sk[-2]
t['price'] = max([self.high_array[-4:]])
t['price'] = max(self.high_array[-4:])
t['time'] = self.line_bar[-1].datetime
t['bars'] = 0
if len(self.skd_top_list) > self.max_hold_bars:
@ -3369,10 +3369,10 @@ class CtaLineBar(object):
# 谷(底部)
elif self.line_sk[-1] > self.line_sk[-2] and self.line_sk[-3] > self.line_sk[-2]:
b = {}
b = dict()
b['type'] = u'B'
b['sk'] = self.line_sk[-2]
b['price'] = min([bar.low_price for bar in self.line_bar[-4:]])
b['price'] = min(self.low_array[-4:])
b['time'] = self.line_bar[-1].datetime
b['bars'] = 0
if len(self.skd_buttom_list) > self.max_hold_bars:

View File

@ -81,7 +81,6 @@ class CtaPosition(CtaComponent):
self.write_log(f'多仓:{pre_long_pos}->{self.long_pos}')
self.write_log(f'净:{pre_pos}->{self.pos}')
return True
def clear(self):

View File

@ -218,7 +218,6 @@ class BinanceFutureData(RestClient):
contracts = load_json(f, auto_save=False)
return contracts
def save_contracts(self):
"""保存合约配置"""
contracts = self.get_contracts()

View File

@ -37,7 +37,6 @@ from vnpy.trader.object import (
from vnpy.trader.event import EVENT_TIMER
from vnpy.event import Event
REST_HOST = "https://www.binance.com"
WEBSOCKET_TRADE_HOST = "wss://stream.binance.com:9443/ws/"
WEBSOCKET_DATA_HOST = "wss://stream.binance.com:9443/stream?streams="
@ -159,6 +158,7 @@ class BinanceGateway(BaseGateway):
and self.status.get('mdws_con', False):
self.status.update({'con': True})
class BinanceRestApi(RestClient):
"""
BINANCE REST API

View File

@ -212,7 +212,6 @@ class BinancefRestApi(RestClient):
self.orders = {}
def sign(self, request: Request) -> Request:
"""
Generate BINANCE signature.
@ -306,7 +305,6 @@ class BinancefRestApi(RestClient):
# 添加到定时查询队列中
self.gateway.query_functions = [self.query_account, self.query_position]
def query_time(self) -> Request:
""""""
data = {
@ -366,7 +364,6 @@ class BinancefRestApi(RestClient):
data=data
)
def query_trade(self, vt_symbol: str = '') -> Request:
""""""
data = {"security": Security.SIGNED}
@ -607,7 +604,6 @@ class BinancefRestApi(RestClient):
self.gateway.write_log("委托信息查询成功")
def on_query_trade(self, data: dict, request: Request) -> None:
""""""
for d in data:
@ -624,6 +620,7 @@ class BinancefRestApi(RestClient):
price=float(d["price"]),
volume=float(d['qty']),
time=time,
datetime=dt,
gateway_name=self.gateway_name,
)
self.gateway.on_trade(trade)
@ -910,6 +907,7 @@ class BinancefTradeWebsocketApi(WebsocketClient):
price=float(ord_data["L"]),
volume=trade_volume,
time=trade_time,
datetime=trade_time,
gateway_name=self.gateway_name,
)
self.gateway.on_trade(trade)

View File

@ -1,7 +1,6 @@
"""
"""
import os
import sys
from abc import ABC, abstractmethod
from typing import Any, Sequence, Dict, List, Optional, Callable
@ -324,6 +323,7 @@ class BaseGateway(ABC):
"""
return self.status
class LocalOrderManager:
"""
Management tool to support use local order id for trading.

View File

@ -48,6 +48,8 @@ class BaseCell(QtWidgets.QTableWidgetItem):
Set text content.
"""
self.setText(str(content))
if isinstance(data, float):
data = round(data, 7)
self._data = data
def get_data(self) -> Any:
@ -737,36 +739,36 @@ class TradingWidget(QtWidgets.QWidget):
if not self.checkFixed.isChecked():
self.price_line.setText(str(tick.last_price))
self.lp_label.setText(str(tick.last_price))
self.bp1_label.setText(str(tick.bid_price_1))
self.bv1_label.setText(str(tick.bid_volume_1))
self.ap1_label.setText(str(tick.ask_price_1))
self.av1_label.setText(str(tick.ask_volume_1))
self.lp_label.setText(str(round(tick.last_price, 7)))
self.bp1_label.setText(str(round(tick.bid_price_1, 7)))
self.bv1_label.setText(str(round(tick.bid_volume_1, 7)))
self.ap1_label.setText(str(round(tick.ask_price_1, 7)))
self.av1_label.setText(str(round(tick.ask_volume_1, 7)))
if tick.pre_close:
r = (tick.last_price / tick.pre_close - 1) * 100
self.return_label.setText(f"{r:.2f}%")
if tick.bid_price_2:
self.bp2_label.setText(str(tick.bid_price_2))
self.bv2_label.setText(str(tick.bid_volume_2))
self.ap2_label.setText(str(tick.ask_price_2))
self.av2_label.setText(str(tick.ask_volume_2))
self.bp2_label.setText(str(round(tick.bid_price_2), 7))
self.bv2_label.setText(str(round(tick.bid_volume_2, 7)))
self.ap2_label.setText(str(round(tick.ask_price_2, 7)))
self.av2_label.setText(str(round(tick.ask_volume_2, 7)))
self.bp3_label.setText(str(tick.bid_price_3))
self.bv3_label.setText(str(tick.bid_volume_3))
self.ap3_label.setText(str(tick.ask_price_3))
self.av3_label.setText(str(tick.ask_volume_3))
self.bp3_label.setText(str(round(tick.bid_price_3, 7)))
self.bv3_label.setText(str(round(tick.bid_volume_3, 7)))
self.ap3_label.setText(str(round(tick.ask_price_3, 7)))
self.av3_label.setText(str(round(tick.ask_volume_3, 7)))
self.bp4_label.setText(str(tick.bid_price_4))
self.bv4_label.setText(str(tick.bid_volume_4))
self.ap4_label.setText(str(tick.ask_price_4))
self.av4_label.setText(str(tick.ask_volume_4))
self.bp4_label.setText(str(round(tick.bid_price_4, 7)))
self.bv4_label.setText(str(round(tick.bid_volume_4, 7)))
self.ap4_label.setText(str(round(tick.ask_price_4, 7)))
self.av4_label.setText(str(round(tick.ask_volume_4, 7)))
self.bp5_label.setText(str(tick.bid_price_5))
self.bv5_label.setText(str(tick.bid_volume_5))
self.ap5_label.setText(str(tick.ask_price_5))
self.av5_label.setText(str(tick.ask_volume_5))
self.bp5_label.setText(str(round(tick.bid_price_5, 7)))
self.bv5_label.setText(str(round(tick.bid_volume_5, 7)))
self.ap5_label.setText(str(round(tick.ask_price_5, 7)))
self.av5_label.setText(str(round(tick.ask_volume_5, 7)))
def set_vt_symbol(self) -> None:
"""

View File

@ -1,9 +1,8 @@
# encoding: UTF-8
# 华富资产
import os
from collections import OrderedDict
from typing import Any, Dict
from typing import Dict
from .utility import get_folder_path
from .util_logger import setup_logger
@ -83,6 +82,7 @@ class LogMonitor(BasicMonitor):
def __init__(self, event_engine=None, monitor_name='LogMonitor'):
super().__init__(event_engine, monitor_name)
class TradeMonitor(BasicMonitor):
"""
Monitor for trade data.
@ -108,6 +108,7 @@ class TradeMonitor(BasicMonitor):
def __init__(self, event_engine=None, monitor_name='TradeMonitor'):
super().__init__(event_engine, monitor_name)
class OrderMonitor(BasicMonitor):
"""
Monitor for order data.
@ -135,6 +136,7 @@ class OrderMonitor(BasicMonitor):
def __init__(self, event_engine=None, monitor_name='OrderMonitor'):
super().__init__(event_engine, monitor_name)
class PositionMonitor(BasicMonitor):
"""
Monitor for position data.

View File

@ -16,6 +16,7 @@ assert os.path.isdir(logs_path)
# 记录pid得文件
pid_file = os.path.abspath(os.path.join(logs_path, 'gpid.txt'))
def _check_pid(pid):
"""
检查pid是否与当前进程pid一致
@ -70,6 +71,7 @@ def update_pid():
# 执行检查
if _check_status():
import sys
print(u'another service is already running...', file=sys.stderr)
exit(0)