[增强] linux下ctp*.so, gw bug fix, float显示截短
This commit is contained in:
parent
aa09f30f06
commit
db6e107b95
BIN
vnpy/api/ctp/vnctpmd.so
Normal file
BIN
vnpy/api/ctp/vnctpmd.so
Normal file
Binary file not shown.
BIN
vnpy/api/ctp/vnctptd.so
Normal file
BIN
vnpy/api/ctp/vnctptd.so
Normal file
Binary file not shown.
@ -311,7 +311,7 @@ class RestClient(object):
|
|||||||
not_finished_executors = [i for i in self._executors if not i.done()]
|
not_finished_executors = [i for i in self._executors if not i.done()]
|
||||||
self._executors = not_finished_executors
|
self._executors = not_finished_executors
|
||||||
|
|
||||||
def _clean_finished_tasks(self, result = None):
|
def _clean_finished_tasks(self, result=None):
|
||||||
with self._tasks_lock:
|
with self._tasks_lock:
|
||||||
not_finished_tasks = [i for i in self._tasks if not i.ready()]
|
not_finished_tasks = [i for i in self._tasks if not i.ready()]
|
||||||
self._tasks = not_finished_tasks
|
self._tasks = not_finished_tasks
|
||||||
|
@ -65,6 +65,7 @@ from vnpy.trader.util_logger import setup_logger
|
|||||||
from vnpy.data.mongo.mongo_data import MongoData
|
from vnpy.data.mongo.mongo_data import MongoData
|
||||||
from uuid import uuid1
|
from uuid import uuid1
|
||||||
|
|
||||||
|
|
||||||
class BackTestingEngine(object):
|
class BackTestingEngine(object):
|
||||||
"""
|
"""
|
||||||
CTA回测引擎
|
CTA回测引擎
|
||||||
@ -106,7 +107,7 @@ class BackTestingEngine(object):
|
|||||||
self.fix_commission = {} # 每手固定手续费
|
self.fix_commission = {} # 每手固定手续费
|
||||||
self.size = {} # 合约大小,默认为1
|
self.size = {} # 合约大小,默认为1
|
||||||
self.price_tick = {} # 价格最小变动
|
self.price_tick = {} # 价格最小变动
|
||||||
self.volume_tick = {} # 合约委托单最小单位
|
self.volume_tick = {} # 合约委托单最小单位
|
||||||
self.margin_rate = {} # 回测合约的保证金比率
|
self.margin_rate = {} # 回测合约的保证金比率
|
||||||
self.price_dict = {} # 登记vt_symbol对应的最新价
|
self.price_dict = {} # 登记vt_symbol对应的最新价
|
||||||
self.contract_dict = {} # 登记vt_symbol得对应合约信息
|
self.contract_dict = {} # 登记vt_symbol得对应合约信息
|
||||||
@ -207,7 +208,7 @@ class BackTestingEngine(object):
|
|||||||
# 回测任务/回测结果,保存在数据库中
|
# 回测任务/回测结果,保存在数据库中
|
||||||
self.mongo_api = None
|
self.mongo_api = None
|
||||||
self.task_id = None
|
self.task_id = None
|
||||||
self.test_setting = None # 回测设置
|
self.test_setting = None # 回测设置
|
||||||
self.strategy_setting = None # 所有回测策略得设置
|
self.strategy_setting = None # 所有回测策略得设置
|
||||||
|
|
||||||
def create_fund_kline(self, name, use_renko=False):
|
def create_fund_kline(self, name, use_renko=False):
|
||||||
@ -543,7 +544,7 @@ class BackTestingEngine(object):
|
|||||||
for symbol, symbol_data in data_dict.items():
|
for symbol, symbol_data in data_dict.items():
|
||||||
self.write_log(u'配置{}数据:{}'.format(symbol, symbol_data))
|
self.write_log(u'配置{}数据:{}'.format(symbol, symbol_data))
|
||||||
self.set_price_tick(symbol, symbol_data.get('price_tick', 1))
|
self.set_price_tick(symbol, symbol_data.get('price_tick', 1))
|
||||||
self.set_volume_tick(symbol, symbol_data.get('min_volume',1))
|
self.set_volume_tick(symbol, symbol_data.get('min_volume', 1))
|
||||||
self.set_slippage(symbol, symbol_data.get('slippage', 0))
|
self.set_slippage(symbol, symbol_data.get('slippage', 0))
|
||||||
self.set_size(symbol, symbol_data.get('symbol_size', 10))
|
self.set_size(symbol, symbol_data.get('symbol_size', 10))
|
||||||
margin_rate = symbol_data.get('margin_rate', 0.1)
|
margin_rate = symbol_data.get('margin_rate', 0.1)
|
||||||
@ -1664,7 +1665,7 @@ class BackTestingEngine(object):
|
|||||||
for t in self.long_position_list:
|
for t in self.long_position_list:
|
||||||
# 当前持仓的保证金
|
# 当前持仓的保证金
|
||||||
cur_occupy_money = min(self.get_price(t.vt_symbol), t.price) * abs(t.volume) * self.get_margin_rate(
|
cur_occupy_money = min(self.get_price(t.vt_symbol), t.price) * abs(t.volume) * self.get_margin_rate(
|
||||||
t.vt_symbol)
|
t.vt_symbol)
|
||||||
|
|
||||||
# 更新该合约短号的累计保证金
|
# 更新该合约短号的累计保证金
|
||||||
underly_symbol = get_underlying_symbol(t.symbol)
|
underly_symbol = get_underlying_symbol(t.symbol)
|
||||||
@ -1680,7 +1681,8 @@ class BackTestingEngine(object):
|
|||||||
if len(self.short_position_list) > 0:
|
if len(self.short_position_list) > 0:
|
||||||
for t in self.short_position_list:
|
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)
|
underly_symbol = get_underlying_symbol(t.symbol)
|
||||||
@ -1695,7 +1697,8 @@ class BackTestingEngine(object):
|
|||||||
|
|
||||||
# 计算多空的保证金累加(对锁的取最大值)
|
# 计算多空的保证金累加(对锁的取最大值)
|
||||||
for underly_symbol in occupy_underly_symbol_set:
|
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
|
self.avaliable = self.net_capital - occupy_money
|
||||||
@ -2070,12 +2073,12 @@ class BackTestingEngine(object):
|
|||||||
self.mongo_api = MongoData(host=save_mongo.get('host', 'localhost'), port=save_mongo.get('port', 27017))
|
self.mongo_api = MongoData(host=save_mongo.get('host', 'localhost'), port=save_mongo.get('port', 27017))
|
||||||
|
|
||||||
d = {
|
d = {
|
||||||
'task_id': self.task_id, # 单实例回测任务id
|
'task_id': self.task_id, # 单实例回测任务id
|
||||||
'name': self.test_name, # 回测实例名称, 策略名+参数+时间
|
'name': self.test_name, # 回测实例名称, 策略名+参数+时间
|
||||||
'group_id': self.test_setting.get('group_id', datetime.now().strftime('%y-%m-%d')), # 回测组合id
|
'group_id': self.test_setting.get('group_id', datetime.now().strftime('%y-%m-%d')), # 回测组合id
|
||||||
'status': 'start',
|
'status': 'start',
|
||||||
'task_start_time': datetime.now(), # 任务开始执行时间
|
'task_start_time': datetime.now(), # 任务开始执行时间
|
||||||
'run_host': socket.gethostname(), # 任务运行得host主机
|
'run_host': socket.gethostname(), # 任务运行得host主机
|
||||||
'test_setting': self.test_setting, # 回测参数
|
'test_setting': self.test_setting, # 回测参数
|
||||||
'strategy_setting': self.strategy_setting, # 策略参数
|
'strategy_setting': self.strategy_setting, # 策略参数
|
||||||
}
|
}
|
||||||
@ -2135,11 +2138,11 @@ class BackTestingEngine(object):
|
|||||||
flt=flt)
|
flt=flt)
|
||||||
|
|
||||||
if d:
|
if d:
|
||||||
d.update({'status': 'finish'}) # 更新状态未完成
|
d.update({'status': 'finish'}) # 更新状态未完成
|
||||||
d.update(result_info) # 补充回测结果
|
d.update(result_info) # 补充回测结果
|
||||||
d.update({'task_finish_time': datetime.now()}) # 更新回测完成时间
|
d.update({'task_finish_time': datetime.now()}) # 更新回测完成时间
|
||||||
d.update({'trade_list': binary.Binary(zlib.compress(pickle.dumps(self.trade_pnl_list)))}) # 更新交易记录
|
d.update({'trade_list': binary.Binary(zlib.compress(pickle.dumps(self.trade_pnl_list)))}) # 更新交易记录
|
||||||
d.update({'daily_list': binary.Binary(zlib.compress(pickle.dumps(self.daily_list)))}) # 更新每日净值记录
|
d.update({'daily_list': binary.Binary(zlib.compress(pickle.dumps(self.daily_list)))}) # 更新每日净值记录
|
||||||
|
|
||||||
self.write_log(u'更新回测结果至数据库')
|
self.write_log(u'更新回测结果至数据库')
|
||||||
|
|
||||||
|
@ -344,7 +344,6 @@ class CtaEngine(BaseEngine):
|
|||||||
holding = self.get_position_holding(position.vt_symbol, position.gateway_name)
|
holding = self.get_position_holding(position.vt_symbol, position.gateway_name)
|
||||||
holding.update_position(position)
|
holding.update_position(position)
|
||||||
|
|
||||||
|
|
||||||
def check_unsubscribed_symbols(self):
|
def check_unsubscribed_symbols(self):
|
||||||
"""检查未订阅合约"""
|
"""检查未订阅合约"""
|
||||||
|
|
||||||
@ -1179,7 +1178,7 @@ class CtaEngine(BaseEngine):
|
|||||||
self.write_log(msg)
|
self.write_log(msg)
|
||||||
return True, msg
|
return True, msg
|
||||||
|
|
||||||
def save_strategy_data(self, select_name: str):
|
def save_strategy_data(self, select_name: str = 'ALL'):
|
||||||
""" save strategy data"""
|
""" save strategy data"""
|
||||||
has_executed = False
|
has_executed = False
|
||||||
msg = ""
|
msg = ""
|
||||||
@ -1215,7 +1214,7 @@ class CtaEngine(BaseEngine):
|
|||||||
self.write_error(u'保存策略{}数据异常:'.format(strategy_name, str(ex)))
|
self.write_error(u'保存策略{}数据异常:'.format(strategy_name, str(ex)))
|
||||||
self.write_error(traceback.format_exc())
|
self.write_error(traceback.format_exc())
|
||||||
|
|
||||||
def save_strategy_snapshot(self, select_name: str):
|
def save_strategy_snapshot(self, select_name: str = 'ALL'):
|
||||||
"""
|
"""
|
||||||
保存策略K线切片数据
|
保存策略K线切片数据
|
||||||
:param select_name:
|
:param select_name:
|
||||||
@ -1607,7 +1606,7 @@ class CtaEngine(BaseEngine):
|
|||||||
try:
|
try:
|
||||||
from vnpy.trader.util_wechat import send_wx_msg
|
from vnpy.trader.util_wechat import send_wx_msg
|
||||||
send_wx_msg(content=msg)
|
send_wx_msg(content=msg)
|
||||||
except Exception as ex:
|
except Exception: # noqa
|
||||||
pass
|
pass
|
||||||
ret_msg = u'持仓不匹配: {}' \
|
ret_msg = u'持仓不匹配: {}' \
|
||||||
.format(pos_compare_result)
|
.format(pos_compare_result)
|
||||||
|
@ -13,9 +13,6 @@ import gc
|
|||||||
import pandas as pd
|
import pandas as pd
|
||||||
import traceback
|
import traceback
|
||||||
import random
|
import random
|
||||||
import bz2
|
|
||||||
import pickle
|
|
||||||
|
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from time import sleep
|
from time import sleep
|
||||||
|
|
||||||
@ -196,7 +193,6 @@ class PortfolioTestingEngine(BackTestingEngine):
|
|||||||
symbol, exchange = extract_vt_symbol(vt_symbol)
|
symbol, exchange = extract_vt_symbol(vt_symbol)
|
||||||
self.load_bar_csv_to_df(vt_symbol, self.bar_csv_file.get(symbol))
|
self.load_bar_csv_to_df(vt_symbol, self.bar_csv_file.get(symbol))
|
||||||
|
|
||||||
|
|
||||||
# 合并数据
|
# 合并数据
|
||||||
self.comine_bar_df()
|
self.comine_bar_df()
|
||||||
|
|
||||||
@ -309,6 +305,7 @@ class PortfolioTestingEngine(BackTestingEngine):
|
|||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
def single_test(test_setting: dict, strategy_setting: dict):
|
def single_test(test_setting: dict, strategy_setting: dict):
|
||||||
"""
|
"""
|
||||||
单一回测
|
单一回测
|
||||||
|
@ -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.object import BarData, TickData, OrderData, TradeData
|
||||||
from vnpy.trader.utility import virtual, append_data, extract_vt_symbol, get_underlying_symbol
|
from vnpy.trader.utility import virtual, append_data, extract_vt_symbol, get_underlying_symbol
|
||||||
|
|
||||||
from .base import StopOrder, EngineType
|
from .base import StopOrder
|
||||||
from vnpy.component.cta_grid_trade import CtaGrid, CtaGridTrade, LOCK_GRID
|
from vnpy.component.cta_grid_trade import CtaGrid, CtaGridTrade
|
||||||
from vnpy.component.cta_position import CtaPosition
|
from vnpy.component.cta_position import CtaPosition
|
||||||
from vnpy.component.cta_policy import CtaPolicy # noqa
|
|
||||||
|
|
||||||
|
|
||||||
class CtaTemplate(ABC):
|
class CtaTemplate(ABC):
|
||||||
"""CTA策略模板"""
|
"""CTA策略模板"""
|
||||||
@ -416,8 +414,6 @@ class CtaTemplate(ABC):
|
|||||||
self.cta_engine.sync_strategy_data(self)
|
self.cta_engine.sync_strategy_data(self)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class CtaFutureTemplate(CtaTemplate):
|
class CtaFutureTemplate(CtaTemplate):
|
||||||
"""
|
"""
|
||||||
合约期货模板
|
合约期货模板
|
||||||
@ -426,7 +422,7 @@ class CtaFutureTemplate(CtaTemplate):
|
|||||||
price_tick = 1 # 商品的最小价格跳动
|
price_tick = 1 # 商品的最小价格跳动
|
||||||
symbol_size = 10 # 商品得合约乘数
|
symbol_size = 10 # 商品得合约乘数
|
||||||
margin_rate = 0.1 # 商品的保证金
|
margin_rate = 0.1 # 商品的保证金
|
||||||
volumn_tick = 1 # 商品最小成交数量
|
volumn_tick = 1 # 商品最小成交数量
|
||||||
|
|
||||||
# 委托类型
|
# 委托类型
|
||||||
order_type = OrderType.LIMIT
|
order_type = OrderType.LIMIT
|
||||||
@ -441,7 +437,7 @@ class CtaFutureTemplate(CtaTemplate):
|
|||||||
backtesting = False
|
backtesting = False
|
||||||
|
|
||||||
# 逻辑过程日志
|
# 逻辑过程日志
|
||||||
dist_fieldnames = ['datetime', 'symbol', 'volume', 'price','margin',
|
dist_fieldnames = ['datetime', 'symbol', 'volume', 'price', 'margin',
|
||||||
'operation', 'signal', 'stop_price', 'target_price',
|
'operation', 'signal', 'stop_price', 'target_price',
|
||||||
'long_pos', 'short_pos']
|
'long_pos', 'short_pos']
|
||||||
|
|
||||||
@ -844,37 +840,7 @@ class CtaFutureTemplate(CtaTemplate):
|
|||||||
self.active_orders.pop(order.vt_orderid, None)
|
self.active_orders.pop(order.vt_orderid, None)
|
||||||
return
|
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)
|
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)
|
pre_status = old_order.get('status', Status.NOTTRADED)
|
||||||
old_order.update({'status': Status.CANCELLED})
|
old_order.update({'status': Status.CANCELLED})
|
||||||
self.write_log(u'委托单状态:{}=>{}'.format(pre_status, old_order.get('status')))
|
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)
|
self.active_orders.pop(order.vt_orderid, None)
|
||||||
return
|
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)
|
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)
|
pre_status = old_order.get('status', Status.NOTTRADED)
|
||||||
old_order.update({'status': Status.CANCELLED})
|
old_order.update({'status': Status.CANCELLED})
|
||||||
self.write_log(u'委托单状态:{}=>{}'.format(pre_status, old_order.get('status')))
|
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):
|
def on_stop_order(self, stop_order: StopOrder):
|
||||||
self.write_log(f'停止单触发:{stop_order.__dict__}')
|
self.write_log(f'停止单触发:{stop_order.__dict__}')
|
||||||
|
|
||||||
|
|
||||||
def grid_check_stop(self):
|
def grid_check_stop(self):
|
||||||
"""
|
"""
|
||||||
网格逐一止损/止盈检查 (根据指数价格进行止损止盈)
|
网格逐一止损/止盈检查 (根据指数价格进行止损止盈)
|
||||||
@ -976,12 +919,12 @@ class CtaFutureTemplate(CtaTemplate):
|
|||||||
if g.stop_price > 0 and g.stop_price > self.cur_price and g.open_status and not g.order_status:
|
if g.stop_price > 0 and g.stop_price > self.cur_price and g.open_status and not g.order_status:
|
||||||
# 调用平仓模块
|
# 调用平仓模块
|
||||||
self.write_log(u'{} {}当前价:{} 触发多单止损线{},开仓价:{},v:{}'.
|
self.write_log(u'{} {}当前价:{} 触发多单止损线{},开仓价:{},v:{}'.
|
||||||
format(self.cur_datetime,
|
format(self.cur_datetime,
|
||||||
self.vt_symbol,
|
self.vt_symbol,
|
||||||
self.cur_price,
|
self.cur_price,
|
||||||
g.stop_price,
|
g.stop_price,
|
||||||
g.open_price,
|
g.open_price,
|
||||||
g.volume))
|
g.volume))
|
||||||
if self.grid_sell(g):
|
if self.grid_sell(g):
|
||||||
self.write_log(u'多单止盈/止损委托成功')
|
self.write_log(u'多单止盈/止损委托成功')
|
||||||
else:
|
else:
|
||||||
@ -993,8 +936,8 @@ class CtaFutureTemplate(CtaTemplate):
|
|||||||
if g.stop_price > 0 and g.stop_price < self.cur_price and g.open_status and not g.order_status:
|
if g.stop_price > 0 and g.stop_price < self.cur_price and g.open_status and not g.order_status:
|
||||||
# 网格止损
|
# 网格止损
|
||||||
self.write_log(u'{} {}当前价:{} 触发空单止损线:{}, 开仓价:{},v:{}'.
|
self.write_log(u'{} {}当前价:{} 触发空单止损线:{}, 开仓价:{},v:{}'.
|
||||||
format(self.cur_datetime, self.vt_symbol, self.cur_price, g.stop_price,
|
format(self.cur_datetime, self.vt_symbol, self.cur_price, g.stop_price,
|
||||||
g.open_price, g.volume))
|
g.open_price, g.volume))
|
||||||
if self.grid_cover(g):
|
if self.grid_cover(g):
|
||||||
self.write_log(u'空单止盈/止损委托成功')
|
self.write_log(u'空单止盈/止损委托成功')
|
||||||
else:
|
else:
|
||||||
@ -1013,16 +956,15 @@ class CtaFutureTemplate(CtaTemplate):
|
|||||||
grid=grid)
|
grid=grid)
|
||||||
if len(vt_orderids) > 0:
|
if len(vt_orderids) > 0:
|
||||||
self.write_log(u'创建{}事务多单,开仓价:{},数量:{},止盈价:{},止损价:{}'
|
self.write_log(u'创建{}事务多单,开仓价:{},数量:{},止盈价:{},止损价:{}'
|
||||||
.format(grid.type, grid.open_price, grid.volume, grid.close_price, grid.stop_price))
|
.format(grid.type, grid.open_price, grid.volume, grid.close_price, grid.stop_price))
|
||||||
self.gt.dn_grids.append(grid)
|
self.gt.dn_grids.append(grid)
|
||||||
self.gt.save()
|
self.gt.save()
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
self.write_error(u'创建{}事务多单,委托失败,开仓价:{},数量:{},止盈价:{}'
|
self.write_error(u'创建{}事务多单,委托失败,开仓价:{},数量:{},止盈价:{}'
|
||||||
.format(grid.type, grid.open_price, grid.volume, grid.close_price))
|
.format(grid.type, grid.open_price, grid.volume, grid.close_price))
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def grid_short(self, grid):
|
def grid_short(self, grid):
|
||||||
"""
|
"""
|
||||||
事务开空仓
|
事务开空仓
|
||||||
@ -1036,14 +978,14 @@ class CtaFutureTemplate(CtaTemplate):
|
|||||||
grid=grid)
|
grid=grid)
|
||||||
if len(vt_orderids) > 0:
|
if len(vt_orderids) > 0:
|
||||||
self.write_log(u'创建{}事务空单,指数开空价:{},主力开仓价:{},数量:{},止盈价:{},止损价:{}'
|
self.write_log(u'创建{}事务空单,指数开空价:{},主力开仓价:{},数量:{},止盈价:{},止损价:{}'
|
||||||
.format(grid.type, grid.open_price, self.cur_price, grid.volume, grid.close_price,
|
.format(grid.type, grid.open_price, self.cur_price, grid.volume, grid.close_price,
|
||||||
grid.stop_price))
|
grid.stop_price))
|
||||||
self.gt.up_grids.append(grid)
|
self.gt.up_grids.append(grid)
|
||||||
self.gt.save()
|
self.gt.save()
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
self.write_error(u'创建{}事务空单,委托失败,开仓价:{},数量:{},止盈价:{}'
|
self.write_error(u'创建{}事务空单,委托失败,开仓价:{},数量:{},止盈价:{}'
|
||||||
.format(grid.type, grid.open_price, grid.volume, grid.close_price))
|
.format(grid.type, grid.open_price, grid.volume, grid.close_price))
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def grid_sell(self, grid):
|
def grid_sell(self, grid):
|
||||||
@ -1302,7 +1244,6 @@ class CtaFutureTemplate(CtaTemplate):
|
|||||||
if len(self.active_orders) == 0:
|
if len(self.active_orders) == 0:
|
||||||
self.entrust = 0
|
self.entrust = 0
|
||||||
|
|
||||||
|
|
||||||
def display_grids(self):
|
def display_grids(self):
|
||||||
"""更新网格显示信息"""
|
"""更新网格显示信息"""
|
||||||
if not self.inited:
|
if not self.inited:
|
||||||
@ -1340,7 +1281,9 @@ class CtaFutureTemplate(CtaTemplate):
|
|||||||
save_path = self.cta_engine.get_data_path()
|
save_path = self.cta_engine.get_data_path()
|
||||||
try:
|
try:
|
||||||
if 'margin' not in dist_data:
|
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:
|
if self.position and 'long_pos' not in dist_data:
|
||||||
dist_data.update({'long_pos': self.position.long_pos})
|
dist_data.update({'long_pos': self.position.long_pos})
|
||||||
if self.position and 'short_pos' not in dist_data:
|
if self.position and 'short_pos' not in dist_data:
|
||||||
@ -1373,5 +1316,3 @@ class CtaFutureTemplate(CtaTemplate):
|
|||||||
if self.backtesting:
|
if self.backtesting:
|
||||||
return
|
return
|
||||||
self.cta_engine.send_wechat(msg=msg, strategy=self)
|
self.cta_engine.send_wechat(msg=msg, strategy=self)
|
||||||
|
|
||||||
|
|
||||||
|
@ -14,7 +14,11 @@ from .template import (
|
|||||||
BarData,
|
BarData,
|
||||||
TradeData,
|
TradeData,
|
||||||
OrderData,
|
OrderData,
|
||||||
CtaTemplate, CtaSignal, TargetPosTemplate, CtaProTemplate, CtaProFutureTemplate) # noqa
|
CtaTemplate,
|
||||||
|
CtaSignal,
|
||||||
|
TargetPosTemplate,
|
||||||
|
CtaProTemplate,
|
||||||
|
CtaProFutureTemplate) # noqa
|
||||||
from vnpy.trader.utility import BarGenerator, ArrayManager # noqa
|
from vnpy.trader.utility import BarGenerator, ArrayManager # noqa
|
||||||
|
|
||||||
from .template_spread import CtaSpreadTemplate
|
from .template_spread import CtaSpreadTemplate
|
||||||
|
@ -715,7 +715,9 @@ class CtaEngine(BaseEngine):
|
|||||||
strategy = self.strategies.get(strategy_name, None)
|
strategy = self.strategies.get(strategy_name, None)
|
||||||
if not strategy:
|
if not strategy:
|
||||||
return False
|
return False
|
||||||
|
if len(vt_symbol) == 0:
|
||||||
|
self.write_error(f'不能为{strategy_name}订阅空白合约')
|
||||||
|
return False
|
||||||
contract = self.main_engine.get_contract(vt_symbol)
|
contract = self.main_engine.get_contract(vt_symbol)
|
||||||
if contract:
|
if contract:
|
||||||
if contract.gateway_name and not gateway_name:
|
if contract.gateway_name and not gateway_name:
|
||||||
@ -1101,7 +1103,7 @@ class CtaEngine(BaseEngine):
|
|||||||
self.write_log(msg)
|
self.write_log(msg)
|
||||||
return True, msg
|
return True, msg
|
||||||
|
|
||||||
def save_strategy_data(self, select_name: str):
|
def save_strategy_data(self, select_name: str = 'ALL'):
|
||||||
""" save strategy data"""
|
""" save strategy data"""
|
||||||
has_executed = False
|
has_executed = False
|
||||||
msg = ""
|
msg = ""
|
||||||
@ -1137,7 +1139,7 @@ class CtaEngine(BaseEngine):
|
|||||||
self.write_error(u'保存策略{}数据异常:'.format(strategy_name, str(ex)))
|
self.write_error(u'保存策略{}数据异常:'.format(strategy_name, str(ex)))
|
||||||
self.write_error(traceback.format_exc())
|
self.write_error(traceback.format_exc())
|
||||||
|
|
||||||
def save_strategy_snapshot(self, select_name: str):
|
def save_strategy_snapshot(self, select_name: str = 'ALL'):
|
||||||
"""
|
"""
|
||||||
保存策略K线切片数据
|
保存策略K线切片数据
|
||||||
:param select_name:
|
:param select_name:
|
||||||
@ -1571,7 +1573,7 @@ class CtaEngine(BaseEngine):
|
|||||||
try:
|
try:
|
||||||
from vnpy.trader.util_wechat import send_wx_msg
|
from vnpy.trader.util_wechat import send_wx_msg
|
||||||
send_wx_msg(content=msg)
|
send_wx_msg(content=msg)
|
||||||
except Exception as ex:
|
except Exception as ex: # noqa
|
||||||
pass
|
pass
|
||||||
ret_msg = u'持仓不匹配: {}' \
|
ret_msg = u'持仓不匹配: {}' \
|
||||||
.format(pos_compare_result)
|
.format(pos_compare_result)
|
||||||
|
@ -1568,7 +1568,8 @@ class CtaProFutureTemplate(CtaProTemplate):
|
|||||||
over_seconds = (dt - order_time).total_seconds()
|
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: # 超过设置的时间还未成交
|
if over_seconds > self.cancel_seconds or force: # 超过设置的时间还未成交
|
||||||
self.write_log(u'超时{}秒未成交,取消委托单:vt_orderid:{},order:{}'
|
self.write_log(u'超时{}秒未成交,取消委托单:vt_orderid:{},order:{}'
|
||||||
.format(over_seconds, vt_orderid, order_info))
|
.format(over_seconds, vt_orderid, order_info))
|
||||||
|
@ -98,7 +98,7 @@ class RpcEngine(BaseEngine):
|
|||||||
|
|
||||||
self.save_setting()
|
self.save_setting()
|
||||||
self.write_log("RPC服务启动成功")
|
self.write_log("RPC服务启动成功")
|
||||||
return True,"RPC服务启动成功"
|
return True, "RPC服务启动成功"
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
""""""
|
""""""
|
||||||
|
@ -3353,10 +3353,10 @@ class CtaLineBar(object):
|
|||||||
# 记录所有SK的顶部和底部
|
# 记录所有SK的顶部和底部
|
||||||
# 峰(顶部)
|
# 峰(顶部)
|
||||||
if self.line_sk[-1] < self.line_sk[-2] and self.line_sk[-3] < self.line_sk[-2]:
|
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['type'] = u'T'
|
||||||
t['sk'] = self.line_sk[-2]
|
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['time'] = self.line_bar[-1].datetime
|
||||||
t['bars'] = 0
|
t['bars'] = 0
|
||||||
if len(self.skd_top_list) > self.max_hold_bars:
|
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]:
|
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['type'] = u'B'
|
||||||
b['sk'] = self.line_sk[-2]
|
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['time'] = self.line_bar[-1].datetime
|
||||||
b['bars'] = 0
|
b['bars'] = 0
|
||||||
if len(self.skd_buttom_list) > self.max_hold_bars:
|
if len(self.skd_buttom_list) > self.max_hold_bars:
|
||||||
|
@ -81,7 +81,6 @@ class CtaPosition(CtaComponent):
|
|||||||
self.write_log(f'多仓:{pre_long_pos}->{self.long_pos}')
|
self.write_log(f'多仓:{pre_long_pos}->{self.long_pos}')
|
||||||
self.write_log(f'净:{pre_pos}->{self.pos}')
|
self.write_log(f'净:{pre_pos}->{self.pos}')
|
||||||
|
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def clear(self):
|
def clear(self):
|
||||||
|
@ -201,7 +201,7 @@ class BinanceFutureData(RestClient):
|
|||||||
"name": name,
|
"name": name,
|
||||||
"price_tick": pricetick,
|
"price_tick": pricetick,
|
||||||
"symbol_size": 20,
|
"symbol_size": 20,
|
||||||
"margin_rate" : round(float(d['requiredMarginPercent']) / 100,5),
|
"margin_rate": round(float(d['requiredMarginPercent']) / 100, 5),
|
||||||
"min_volume": min_volume,
|
"min_volume": min_volume,
|
||||||
"product": Product.FUTURES.value,
|
"product": Product.FUTURES.value,
|
||||||
"commission_rate": 0.005
|
"commission_rate": 0.005
|
||||||
@ -218,7 +218,6 @@ class BinanceFutureData(RestClient):
|
|||||||
contracts = load_json(f, auto_save=False)
|
contracts = load_json(f, auto_save=False)
|
||||||
return contracts
|
return contracts
|
||||||
|
|
||||||
|
|
||||||
def save_contracts(self):
|
def save_contracts(self):
|
||||||
"""保存合约配置"""
|
"""保存合约配置"""
|
||||||
contracts = self.get_contracts()
|
contracts = self.get_contracts()
|
||||||
|
@ -37,7 +37,6 @@ from vnpy.trader.object import (
|
|||||||
from vnpy.trader.event import EVENT_TIMER
|
from vnpy.trader.event import EVENT_TIMER
|
||||||
from vnpy.event import Event
|
from vnpy.event import Event
|
||||||
|
|
||||||
|
|
||||||
REST_HOST = "https://www.binance.com"
|
REST_HOST = "https://www.binance.com"
|
||||||
WEBSOCKET_TRADE_HOST = "wss://stream.binance.com:9443/ws/"
|
WEBSOCKET_TRADE_HOST = "wss://stream.binance.com:9443/ws/"
|
||||||
WEBSOCKET_DATA_HOST = "wss://stream.binance.com:9443/stream?streams="
|
WEBSOCKET_DATA_HOST = "wss://stream.binance.com:9443/stream?streams="
|
||||||
@ -159,6 +158,7 @@ class BinanceGateway(BaseGateway):
|
|||||||
and self.status.get('mdws_con', False):
|
and self.status.get('mdws_con', False):
|
||||||
self.status.update({'con': True})
|
self.status.update({'con': True})
|
||||||
|
|
||||||
|
|
||||||
class BinanceRestApi(RestClient):
|
class BinanceRestApi(RestClient):
|
||||||
"""
|
"""
|
||||||
BINANCE REST API
|
BINANCE REST API
|
||||||
@ -234,12 +234,12 @@ class BinanceRestApi(RestClient):
|
|||||||
return request
|
return request
|
||||||
|
|
||||||
def connect(
|
def connect(
|
||||||
self,
|
self,
|
||||||
key: str,
|
key: str,
|
||||||
secret: str,
|
secret: str,
|
||||||
session_number: int,
|
session_number: int,
|
||||||
proxy_host: str,
|
proxy_host: str,
|
||||||
proxy_port: int
|
proxy_port: int
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Initialize connection to REST server.
|
Initialize connection to REST server.
|
||||||
@ -250,7 +250,7 @@ class BinanceRestApi(RestClient):
|
|||||||
self.proxy_host = proxy_host
|
self.proxy_host = proxy_host
|
||||||
|
|
||||||
self.connect_time = (
|
self.connect_time = (
|
||||||
int(datetime.now().strftime("%y%m%d%H%M%S")) * self.order_count
|
int(datetime.now().strftime("%y%m%d%H%M%S")) * self.order_count
|
||||||
)
|
)
|
||||||
|
|
||||||
self.init(REST_HOST, proxy_host, proxy_port)
|
self.init(REST_HOST, proxy_host, proxy_port)
|
||||||
@ -504,7 +504,7 @@ class BinanceRestApi(RestClient):
|
|||||||
self.gateway.write_log(msg)
|
self.gateway.write_log(msg)
|
||||||
|
|
||||||
def on_send_order_error(
|
def on_send_order_error(
|
||||||
self, exception_type: type, exception_value: Exception, tb, request: Request
|
self, exception_type: type, exception_value: Exception, tb, request: Request
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Callback when sending order caused exception.
|
Callback when sending order caused exception.
|
||||||
@ -545,13 +545,13 @@ class BinanceRestApi(RestClient):
|
|||||||
"symbol": req.symbol,
|
"symbol": req.symbol,
|
||||||
"interval": INTERVAL_VT2BINANCE[req.interval],
|
"interval": INTERVAL_VT2BINANCE[req.interval],
|
||||||
"limit": limit,
|
"limit": limit,
|
||||||
"startTime": start_time * 1000, # convert to millisecond
|
"startTime": start_time * 1000, # convert to millisecond
|
||||||
}
|
}
|
||||||
|
|
||||||
# Add end time if specified
|
# Add end time if specified
|
||||||
if req.end:
|
if req.end:
|
||||||
end_time = int(datetime.timestamp(req.end))
|
end_time = int(datetime.timestamp(req.end))
|
||||||
params["endTime"] = end_time * 1000 # convert to millisecond
|
params["endTime"] = end_time * 1000 # convert to millisecond
|
||||||
|
|
||||||
# Get response from server
|
# Get response from server
|
||||||
resp = self.request(
|
resp = self.request(
|
||||||
@ -576,7 +576,7 @@ class BinanceRestApi(RestClient):
|
|||||||
buf = []
|
buf = []
|
||||||
|
|
||||||
for l in data:
|
for l in data:
|
||||||
dt = datetime.fromtimestamp(l[0] / 1000) # convert to second
|
dt = datetime.fromtimestamp(l[0] / 1000) # convert to second
|
||||||
|
|
||||||
bar = BarData(
|
bar = BarData(
|
||||||
symbol=req.symbol,
|
symbol=req.symbol,
|
||||||
|
@ -212,7 +212,6 @@ class BinancefRestApi(RestClient):
|
|||||||
|
|
||||||
self.orders = {}
|
self.orders = {}
|
||||||
|
|
||||||
|
|
||||||
def sign(self, request: Request) -> Request:
|
def sign(self, request: Request) -> Request:
|
||||||
"""
|
"""
|
||||||
Generate BINANCE signature.
|
Generate BINANCE signature.
|
||||||
@ -262,13 +261,13 @@ class BinancefRestApi(RestClient):
|
|||||||
return request
|
return request
|
||||||
|
|
||||||
def connect(
|
def connect(
|
||||||
self,
|
self,
|
||||||
key: str,
|
key: str,
|
||||||
secret: str,
|
secret: str,
|
||||||
session_number: int,
|
session_number: int,
|
||||||
server: str,
|
server: str,
|
||||||
proxy_host: str,
|
proxy_host: str,
|
||||||
proxy_port: int
|
proxy_port: int
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
"""
|
||||||
Initialize connection to REST server.
|
Initialize connection to REST server.
|
||||||
@ -280,7 +279,7 @@ class BinancefRestApi(RestClient):
|
|||||||
self.server = server
|
self.server = server
|
||||||
|
|
||||||
self.connect_time = (
|
self.connect_time = (
|
||||||
int(datetime.now().strftime("%y%m%d%H%M%S")) * self.order_count
|
int(datetime.now().strftime("%y%m%d%H%M%S")) * self.order_count
|
||||||
)
|
)
|
||||||
|
|
||||||
if self.server == "REAL":
|
if self.server == "REAL":
|
||||||
@ -306,7 +305,6 @@ class BinancefRestApi(RestClient):
|
|||||||
# 添加到定时查询队列中
|
# 添加到定时查询队列中
|
||||||
self.gateway.query_functions = [self.query_account, self.query_position]
|
self.gateway.query_functions = [self.query_account, self.query_position]
|
||||||
|
|
||||||
|
|
||||||
def query_time(self) -> Request:
|
def query_time(self) -> Request:
|
||||||
""""""
|
""""""
|
||||||
data = {
|
data = {
|
||||||
@ -366,12 +364,11 @@ class BinancefRestApi(RestClient):
|
|||||||
data=data
|
data=data
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def query_trade(self, vt_symbol: str = '') -> Request:
|
def query_trade(self, vt_symbol: str = '') -> Request:
|
||||||
""""""
|
""""""
|
||||||
data = {"security": Security.SIGNED}
|
data = {"security": Security.SIGNED}
|
||||||
if vt_symbol:
|
if vt_symbol:
|
||||||
if '.' in vt_symbol:
|
if '.' in vt_symbol:
|
||||||
vt_symbol = vt_symbol.split('.')[0]
|
vt_symbol = vt_symbol.split('.')[0]
|
||||||
data.update({'symbol': vt_symbol})
|
data.update({'symbol': vt_symbol})
|
||||||
|
|
||||||
@ -607,7 +604,6 @@ class BinancefRestApi(RestClient):
|
|||||||
|
|
||||||
self.gateway.write_log("委托信息查询成功")
|
self.gateway.write_log("委托信息查询成功")
|
||||||
|
|
||||||
|
|
||||||
def on_query_trade(self, data: dict, request: Request) -> None:
|
def on_query_trade(self, data: dict, request: Request) -> None:
|
||||||
""""""
|
""""""
|
||||||
for d in data:
|
for d in data:
|
||||||
@ -624,6 +620,7 @@ class BinancefRestApi(RestClient):
|
|||||||
price=float(d["price"]),
|
price=float(d["price"]),
|
||||||
volume=float(d['qty']),
|
volume=float(d['qty']),
|
||||||
time=time,
|
time=time,
|
||||||
|
datetime=dt,
|
||||||
gateway_name=self.gateway_name,
|
gateway_name=self.gateway_name,
|
||||||
)
|
)
|
||||||
self.gateway.on_trade(trade)
|
self.gateway.on_trade(trade)
|
||||||
@ -664,7 +661,7 @@ class BinancefRestApi(RestClient):
|
|||||||
name=name,
|
name=name,
|
||||||
pricetick=pricetick,
|
pricetick=pricetick,
|
||||||
size=symbol_size,
|
size=symbol_size,
|
||||||
margin_rate= round(float(d['requiredMarginPercent'])/100, 5),
|
margin_rate=round(float(d['requiredMarginPercent']) / 100, 5),
|
||||||
min_volume=min_volume,
|
min_volume=min_volume,
|
||||||
product=Product.FUTURES,
|
product=Product.FUTURES,
|
||||||
history_data=True,
|
history_data=True,
|
||||||
@ -692,7 +689,7 @@ class BinancefRestApi(RestClient):
|
|||||||
self.gateway.write_log(msg)
|
self.gateway.write_log(msg)
|
||||||
|
|
||||||
def on_send_order_error(
|
def on_send_order_error(
|
||||||
self, exception_type: type, exception_value: Exception, tb, request: Request
|
self, exception_type: type, exception_value: Exception, tb, request: Request
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
"""
|
||||||
Callback when sending order caused exception.
|
Callback when sending order caused exception.
|
||||||
@ -738,13 +735,13 @@ class BinancefRestApi(RestClient):
|
|||||||
"symbol": req.symbol,
|
"symbol": req.symbol,
|
||||||
"interval": INTERVAL_VT2BINANCEF[req.interval],
|
"interval": INTERVAL_VT2BINANCEF[req.interval],
|
||||||
"limit": limit,
|
"limit": limit,
|
||||||
"startTime": start_time * 1000, # convert to millisecond
|
"startTime": start_time * 1000, # convert to millisecond
|
||||||
}
|
}
|
||||||
|
|
||||||
# Add end time if specified
|
# Add end time if specified
|
||||||
if req.end:
|
if req.end:
|
||||||
end_time = int(datetime.timestamp(req.end))
|
end_time = int(datetime.timestamp(req.end))
|
||||||
params["endTime"] = end_time * 1000 # convert to millisecond
|
params["endTime"] = end_time * 1000 # convert to millisecond
|
||||||
|
|
||||||
# Get response from server
|
# Get response from server
|
||||||
resp = self.request(
|
resp = self.request(
|
||||||
@ -769,7 +766,7 @@ class BinancefRestApi(RestClient):
|
|||||||
buf = []
|
buf = []
|
||||||
|
|
||||||
for l in data:
|
for l in data:
|
||||||
dt = datetime.fromtimestamp(l[0] / 1000) # convert to second
|
dt = datetime.fromtimestamp(l[0] / 1000) # convert to second
|
||||||
|
|
||||||
bar = BarData(
|
bar = BarData(
|
||||||
symbol=req.symbol,
|
symbol=req.symbol,
|
||||||
@ -910,6 +907,7 @@ class BinancefTradeWebsocketApi(WebsocketClient):
|
|||||||
price=float(ord_data["L"]),
|
price=float(ord_data["L"]),
|
||||||
volume=trade_volume,
|
volume=trade_volume,
|
||||||
time=trade_time,
|
time=trade_time,
|
||||||
|
datetime=trade_time,
|
||||||
gateway_name=self.gateway_name,
|
gateway_name=self.gateway_name,
|
||||||
)
|
)
|
||||||
self.gateway.on_trade(trade)
|
self.gateway.on_trade(trade)
|
||||||
@ -928,10 +926,10 @@ class BinancefDataWebsocketApi(WebsocketClient):
|
|||||||
self.ticks: Dict[str, TickData] = {}
|
self.ticks: Dict[str, TickData] = {}
|
||||||
|
|
||||||
def connect(
|
def connect(
|
||||||
self,
|
self,
|
||||||
proxy_host: str,
|
proxy_host: str,
|
||||||
proxy_port: int,
|
proxy_port: int,
|
||||||
server: str
|
server: str
|
||||||
) -> None:
|
) -> None:
|
||||||
""""""
|
""""""
|
||||||
self.proxy_host = proxy_host
|
self.proxy_host = proxy_host
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
"""
|
"""
|
||||||
import os
|
|
||||||
import sys
|
import sys
|
||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
from typing import Any, Sequence, Dict, List, Optional, Callable
|
from typing import Any, Sequence, Dict, List, Optional, Callable
|
||||||
@ -324,6 +323,7 @@ class BaseGateway(ABC):
|
|||||||
"""
|
"""
|
||||||
return self.status
|
return self.status
|
||||||
|
|
||||||
|
|
||||||
class LocalOrderManager:
|
class LocalOrderManager:
|
||||||
"""
|
"""
|
||||||
Management tool to support use local order id for trading.
|
Management tool to support use local order id for trading.
|
||||||
|
@ -48,6 +48,8 @@ class BaseCell(QtWidgets.QTableWidgetItem):
|
|||||||
Set text content.
|
Set text content.
|
||||||
"""
|
"""
|
||||||
self.setText(str(content))
|
self.setText(str(content))
|
||||||
|
if isinstance(data, float):
|
||||||
|
data = round(data, 7)
|
||||||
self._data = data
|
self._data = data
|
||||||
|
|
||||||
def get_data(self) -> Any:
|
def get_data(self) -> Any:
|
||||||
@ -737,36 +739,36 @@ class TradingWidget(QtWidgets.QWidget):
|
|||||||
if not self.checkFixed.isChecked():
|
if not self.checkFixed.isChecked():
|
||||||
self.price_line.setText(str(tick.last_price))
|
self.price_line.setText(str(tick.last_price))
|
||||||
|
|
||||||
self.lp_label.setText(str(tick.last_price))
|
self.lp_label.setText(str(round(tick.last_price, 7)))
|
||||||
self.bp1_label.setText(str(tick.bid_price_1))
|
self.bp1_label.setText(str(round(tick.bid_price_1, 7)))
|
||||||
self.bv1_label.setText(str(tick.bid_volume_1))
|
self.bv1_label.setText(str(round(tick.bid_volume_1, 7)))
|
||||||
self.ap1_label.setText(str(tick.ask_price_1))
|
self.ap1_label.setText(str(round(tick.ask_price_1, 7)))
|
||||||
self.av1_label.setText(str(tick.ask_volume_1))
|
self.av1_label.setText(str(round(tick.ask_volume_1, 7)))
|
||||||
|
|
||||||
if tick.pre_close:
|
if tick.pre_close:
|
||||||
r = (tick.last_price / tick.pre_close - 1) * 100
|
r = (tick.last_price / tick.pre_close - 1) * 100
|
||||||
self.return_label.setText(f"{r:.2f}%")
|
self.return_label.setText(f"{r:.2f}%")
|
||||||
|
|
||||||
if tick.bid_price_2:
|
if tick.bid_price_2:
|
||||||
self.bp2_label.setText(str(tick.bid_price_2))
|
self.bp2_label.setText(str(round(tick.bid_price_2), 7))
|
||||||
self.bv2_label.setText(str(tick.bid_volume_2))
|
self.bv2_label.setText(str(round(tick.bid_volume_2, 7)))
|
||||||
self.ap2_label.setText(str(tick.ask_price_2))
|
self.ap2_label.setText(str(round(tick.ask_price_2, 7)))
|
||||||
self.av2_label.setText(str(tick.ask_volume_2))
|
self.av2_label.setText(str(round(tick.ask_volume_2, 7)))
|
||||||
|
|
||||||
self.bp3_label.setText(str(tick.bid_price_3))
|
self.bp3_label.setText(str(round(tick.bid_price_3, 7)))
|
||||||
self.bv3_label.setText(str(tick.bid_volume_3))
|
self.bv3_label.setText(str(round(tick.bid_volume_3, 7)))
|
||||||
self.ap3_label.setText(str(tick.ask_price_3))
|
self.ap3_label.setText(str(round(tick.ask_price_3, 7)))
|
||||||
self.av3_label.setText(str(tick.ask_volume_3))
|
self.av3_label.setText(str(round(tick.ask_volume_3, 7)))
|
||||||
|
|
||||||
self.bp4_label.setText(str(tick.bid_price_4))
|
self.bp4_label.setText(str(round(tick.bid_price_4, 7)))
|
||||||
self.bv4_label.setText(str(tick.bid_volume_4))
|
self.bv4_label.setText(str(round(tick.bid_volume_4, 7)))
|
||||||
self.ap4_label.setText(str(tick.ask_price_4))
|
self.ap4_label.setText(str(round(tick.ask_price_4, 7)))
|
||||||
self.av4_label.setText(str(tick.ask_volume_4))
|
self.av4_label.setText(str(round(tick.ask_volume_4, 7)))
|
||||||
|
|
||||||
self.bp5_label.setText(str(tick.bid_price_5))
|
self.bp5_label.setText(str(round(tick.bid_price_5, 7)))
|
||||||
self.bv5_label.setText(str(tick.bid_volume_5))
|
self.bv5_label.setText(str(round(tick.bid_volume_5, 7)))
|
||||||
self.ap5_label.setText(str(tick.ask_price_5))
|
self.ap5_label.setText(str(round(tick.ask_price_5, 7)))
|
||||||
self.av5_label.setText(str(tick.ask_volume_5))
|
self.av5_label.setText(str(round(tick.ask_volume_5, 7)))
|
||||||
|
|
||||||
def set_vt_symbol(self) -> None:
|
def set_vt_symbol(self) -> None:
|
||||||
"""
|
"""
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
# encoding: UTF-8
|
# encoding: UTF-8
|
||||||
# 华富资产
|
# 华富资产
|
||||||
|
|
||||||
import os
|
|
||||||
from collections import OrderedDict
|
from typing import Dict
|
||||||
from typing import Any, Dict
|
|
||||||
|
|
||||||
from .utility import get_folder_path
|
from .utility import get_folder_path
|
||||||
from .util_logger import setup_logger
|
from .util_logger import setup_logger
|
||||||
@ -83,6 +82,7 @@ class LogMonitor(BasicMonitor):
|
|||||||
def __init__(self, event_engine=None, monitor_name='LogMonitor'):
|
def __init__(self, event_engine=None, monitor_name='LogMonitor'):
|
||||||
super().__init__(event_engine, monitor_name)
|
super().__init__(event_engine, monitor_name)
|
||||||
|
|
||||||
|
|
||||||
class TradeMonitor(BasicMonitor):
|
class TradeMonitor(BasicMonitor):
|
||||||
"""
|
"""
|
||||||
Monitor for trade data.
|
Monitor for trade data.
|
||||||
@ -108,6 +108,7 @@ class TradeMonitor(BasicMonitor):
|
|||||||
def __init__(self, event_engine=None, monitor_name='TradeMonitor'):
|
def __init__(self, event_engine=None, monitor_name='TradeMonitor'):
|
||||||
super().__init__(event_engine, monitor_name)
|
super().__init__(event_engine, monitor_name)
|
||||||
|
|
||||||
|
|
||||||
class OrderMonitor(BasicMonitor):
|
class OrderMonitor(BasicMonitor):
|
||||||
"""
|
"""
|
||||||
Monitor for order data.
|
Monitor for order data.
|
||||||
@ -135,6 +136,7 @@ class OrderMonitor(BasicMonitor):
|
|||||||
def __init__(self, event_engine=None, monitor_name='OrderMonitor'):
|
def __init__(self, event_engine=None, monitor_name='OrderMonitor'):
|
||||||
super().__init__(event_engine, monitor_name)
|
super().__init__(event_engine, monitor_name)
|
||||||
|
|
||||||
|
|
||||||
class PositionMonitor(BasicMonitor):
|
class PositionMonitor(BasicMonitor):
|
||||||
"""
|
"""
|
||||||
Monitor for position data.
|
Monitor for position data.
|
||||||
|
@ -16,6 +16,7 @@ assert os.path.isdir(logs_path)
|
|||||||
# 记录pid得文件
|
# 记录pid得文件
|
||||||
pid_file = os.path.abspath(os.path.join(logs_path, 'gpid.txt'))
|
pid_file = os.path.abspath(os.path.join(logs_path, 'gpid.txt'))
|
||||||
|
|
||||||
|
|
||||||
def _check_pid(pid):
|
def _check_pid(pid):
|
||||||
"""
|
"""
|
||||||
检查pid是否与当前进程pid一致
|
检查pid是否与当前进程pid一致
|
||||||
@ -70,6 +71,7 @@ def update_pid():
|
|||||||
# 执行检查
|
# 执行检查
|
||||||
if _check_status():
|
if _check_status():
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
print(u'another service is already running...', file=sys.stderr)
|
print(u'another service is already running...', file=sys.stderr)
|
||||||
exit(0)
|
exit(0)
|
||||||
|
|
||||||
|
@ -234,7 +234,7 @@ def get_folder_path(folder_name: str) -> Path:
|
|||||||
folder_path = TEMP_DIR.joinpath(folder_name)
|
folder_path = TEMP_DIR.joinpath(folder_name)
|
||||||
if not folder_path.exists():
|
if not folder_path.exists():
|
||||||
os.makedirs(str(folder_path))
|
os.makedirs(str(folder_path))
|
||||||
#folder_path.mkdir()
|
# folder_path.mkdir()
|
||||||
return folder_path
|
return folder_path
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user