[update] 兼容各类接口得订单逻辑;升级天勤
This commit is contained in:
parent
55b207f5db
commit
39a231cbdf
@ -10,6 +10,10 @@ github 链接: https://github.com/msincenselee/vnpy
|
|||||||
gitee 链接: https://gitee.com/vnpy2/vnpy
|
gitee 链接: https://gitee.com/vnpy2/vnpy
|
||||||
|
|
||||||
###Fork版本主要改进如下
|
###Fork版本主要改进如下
|
||||||
|
19、期权CTA引擎
|
||||||
|
|
||||||
|
-vnpy.app.cta_option
|
||||||
|
+ 支持股票ETF期权的CTA策略
|
||||||
|
|
||||||
18、CTA股票选股引擎
|
18、CTA股票选股引擎
|
||||||
|
|
||||||
@ -163,11 +167,13 @@ QQ/Wechat:28888502
|
|||||||
|
|
||||||
系列在线课程
|
系列在线课程
|
||||||
|
|
||||||
|
2022 期货CTA课程: http://www.uquant.org/course/49
|
||||||
|
|
||||||
2021 股票CTA实战课程:http://www.uquant.org/course/49
|
2021 股票CTA实战课程:http://www.uquant.org/course/49
|
||||||
|
|
||||||
2021 期货缠论高级课程:http://www.uquant.org/course/48
|
2021 期货缠论高级课程:http://www.uquant.org/course/48
|
||||||
|
|
||||||
2021 数字货币CTA课程:http://www.uquant.org/course/46
|
2021 数字CTA课程:http://www.uquant.org/course/46
|
||||||
|
|
||||||
2020 期货套利课程:http://www.uquant.org/course/43
|
2020 期货套利课程:http://www.uquant.org/course/43
|
||||||
|
|
||||||
|
6
prod/Matrix08/win_start.bat
Normal file
6
prod/Matrix08/win_start.bat
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
:: 启动脚本
|
||||||
|
:: 进入盘、目录
|
||||||
|
c:
|
||||||
|
cd C:\GitHub\msincenselee_vnpy\prod\Matrix08
|
||||||
|
:: 启动无界面程序
|
||||||
|
C:\Users\incen\AppData\Local\conda\conda\envs\py37\python run_service.py
|
@ -11,7 +11,7 @@ import pandas as pd
|
|||||||
from contextlib import closing
|
from contextlib import closing
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
import argparse
|
import argparse
|
||||||
from tqsdk import TqApi, TqSim
|
from tqsdk import TqApi, TqSim,TqAuth
|
||||||
|
|
||||||
vnpy_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))
|
vnpy_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))
|
||||||
if vnpy_root not in sys.path:
|
if vnpy_root not in sys.path:
|
||||||
@ -21,7 +21,7 @@ os.environ["VNPY_TESTING"] = "1"
|
|||||||
|
|
||||||
from vnpy.data.tdx.tdx_future_data import get_future_contracts, Exchange
|
from vnpy.data.tdx.tdx_future_data import get_future_contracts, Exchange
|
||||||
from vnpy.trader.utility import get_csv_last_dt, get_underlying_symbol, extract_vt_symbol
|
from vnpy.trader.utility import get_csv_last_dt, get_underlying_symbol, extract_vt_symbol
|
||||||
from vnpy.data.tq.downloader import DataDownloader
|
from vnpy.data.tq.downloader import DataDownloader,get_account_config
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
if len(sys.argv) <= 1:
|
if len(sys.argv) <= 1:
|
||||||
@ -36,9 +36,9 @@ if __name__ == "__main__":
|
|||||||
if len(args.symbol) == 0:
|
if len(args.symbol) == 0:
|
||||||
print('下载合约未设定 参数 -s rb2010')
|
print('下载合约未设定 参数 -s rb2010')
|
||||||
os._exit(0)
|
os._exit(0)
|
||||||
|
auth_dict = get_account_config()
|
||||||
# 开始下载(使用快期的免费行情websocket)
|
# 开始下载(使用快期的免费行情websocket)
|
||||||
api = TqApi(account=TqSim(), url="wss://u.shinnytech.com/t/md/front/mobile")
|
api = TqApi(account=TqSim(), auth=TqAuth(auth_dict['user_name'],auth_dict['password'])) # url="wss://u.shinnytech.com/t/md/front/mobile"
|
||||||
download_tasks = {}
|
download_tasks = {}
|
||||||
begin_date = datetime.strptime(args.begin, '%Y%m%d')
|
begin_date = datetime.strptime(args.begin, '%Y%m%d')
|
||||||
end_date = datetime.strptime(args.end, '%Y%m%d')
|
end_date = datetime.strptime(args.end, '%Y%m%d')
|
||||||
|
@ -412,6 +412,10 @@ class CtaOptionEngine(BaseEngine):
|
|||||||
if not strategy:
|
if not strategy:
|
||||||
if order.vt_orderid in self.internal_orderids:
|
if order.vt_orderid in self.internal_orderids:
|
||||||
self.write_log(f'委托更新 => 内部仓位: {print_dict(order.__dict__)}')
|
self.write_log(f'委托更新 => 内部仓位: {print_dict(order.__dict__)}')
|
||||||
|
if order.sys_orderid and order.sys_orderid != order.orderid and order.sys_orderid not in self.internal_orderids:
|
||||||
|
self.write_log(f'添加系统编号 {order.sys_orderid}=> 内部订单')
|
||||||
|
self.internal_orderids.add(order.sys_orderid)
|
||||||
|
|
||||||
# self.write_log(f'当前策略侦听委托单:{list(self.orderid_strategy_map.keys())}')
|
# self.write_log(f'当前策略侦听委托单:{list(self.orderid_strategy_map.keys())}')
|
||||||
if order.type != OrderType.STOP:
|
if order.type != OrderType.STOP:
|
||||||
if order.status in [Status.ALLTRADED, Status.CANCELLED, Status.REJECTED]:
|
if order.status in [Status.ALLTRADED, Status.CANCELLED, Status.REJECTED]:
|
||||||
@ -425,6 +429,9 @@ class CtaOptionEngine(BaseEngine):
|
|||||||
self.write_log(f'委托更新 => 系统账号 => {print_dict(order.__dict__)}')
|
self.write_log(f'委托更新 => 系统账号 => {print_dict(order.__dict__)}')
|
||||||
return
|
return
|
||||||
self.write_log(f'委托更新:{order.vt_orderid} => 策略:{strategy.strategy_name}')
|
self.write_log(f'委托更新:{order.vt_orderid} => 策略:{strategy.strategy_name}')
|
||||||
|
if len(order.sys_orderid) > 0 and order.sys_orderid not in self.orderid_strategy_map:
|
||||||
|
self.write_log(f'登记系统委托号 {order.sys_orderid} => 策略:{strategy.strategy_name} 映射')
|
||||||
|
|
||||||
# Remove vt_orderid if order is no longer active.
|
# Remove vt_orderid if order is no longer active.
|
||||||
vt_orderids = self.strategy_orderid_map[strategy.strategy_name]
|
vt_orderids = self.strategy_orderid_map[strategy.strategy_name]
|
||||||
if order.vt_orderid in vt_orderids and not order.is_active():
|
if order.vt_orderid in vt_orderids and not order.is_active():
|
||||||
@ -468,7 +475,7 @@ class CtaOptionEngine(BaseEngine):
|
|||||||
if not strategy:
|
if not strategy:
|
||||||
|
|
||||||
# 属于内部单子
|
# 属于内部单子
|
||||||
if trade.vt_orderid in self.internal_orderids:
|
if trade.vt_orderid in self.internal_orderids or trade.sys_orderid in self.internal_orderids:
|
||||||
cur_pos = self.net_pos_holding.get(trade.vt_symbol, 0)
|
cur_pos = self.net_pos_holding.get(trade.vt_symbol, 0)
|
||||||
if trade.direction == Direction.LONG:
|
if trade.direction == Direction.LONG:
|
||||||
new_pos = cur_pos + trade.volume
|
new_pos = cur_pos + trade.volume
|
||||||
@ -478,13 +485,18 @@ class CtaOptionEngine(BaseEngine):
|
|||||||
self.write_log(f'成交单:trade:{print_dict(trade.__dict__)}')
|
self.write_log(f'成交单:trade:{print_dict(trade.__dict__)}')
|
||||||
self.net_pos_holding.update({trade.vt_symbol: new_pos})
|
self.net_pos_holding.update({trade.vt_symbol: new_pos})
|
||||||
self.save_internal_data()
|
self.save_internal_data()
|
||||||
|
return
|
||||||
|
|
||||||
|
if trade.sys_orderid and trade.sys_orderid in self.orderid_strategy_map:
|
||||||
|
self.write_log(f'使用系统委托单号{trade.sys_orderid} => 策略')
|
||||||
|
strategy = self.orderid_strategy_map.get(trade.sys_orderid, None)
|
||||||
|
|
||||||
# 可能是其他实例得
|
# 可能是其他实例得
|
||||||
else:
|
if not strategy:
|
||||||
self.write_log(f'成交更新 => 没有对应的策略设置:trade:{trade.__dict__}')
|
self.write_log(f'成交更新 => 没有对应的策略设置:trade:{trade.__dict__}')
|
||||||
self.write_log(f'成交更新 => 当前策略侦听委托单:{list(self.orderid_strategy_map.keys())}')
|
self.write_log(f'成交更新 => 当前策略侦听委托单:{list(self.orderid_strategy_map.keys())}')
|
||||||
self.write_log(f'成交更新 => 当前内部订单清单:{self.internal_orderids}')
|
self.write_log(f'成交更新 => 当前内部订单清单:{self.internal_orderids}')
|
||||||
return
|
return
|
||||||
|
|
||||||
self.write_log(f'成交更新 =>:{trade.vt_orderid} => 策略:{strategy.strategy_name}')
|
self.write_log(f'成交更新 =>:{trade.vt_orderid} => 策略:{strategy.strategy_name}')
|
||||||
|
|
||||||
|
@ -353,6 +353,11 @@ class CtaEngine(BaseEngine):
|
|||||||
self.write_log(f'当前策略侦听委托单:{list(self.orderid_strategy_map.keys())}')
|
self.write_log(f'当前策略侦听委托单:{list(self.orderid_strategy_map.keys())}')
|
||||||
return
|
return
|
||||||
self.write_log(f'委托更新:{order.vt_orderid} => 策略:{strategy.strategy_name}')
|
self.write_log(f'委托更新:{order.vt_orderid} => 策略:{strategy.strategy_name}')
|
||||||
|
|
||||||
|
if len(order.sys_orderid) > 0 and order.sys_orderid not in self.orderid_strategy_map:
|
||||||
|
self.write_log(f'登记系统委托号 {order.sys_orderid} => 策略:{strategy.strategy_name} 映射')
|
||||||
|
self.orderid_strategy_map.update({order.sys_orderid: strategy})
|
||||||
|
|
||||||
# Remove vt_orderid if order is no longer active.
|
# Remove vt_orderid if order is no longer active.
|
||||||
vt_orderids = self.strategy_orderid_map[strategy.strategy_name]
|
vt_orderids = self.strategy_orderid_map[strategy.strategy_name]
|
||||||
if order.vt_orderid in vt_orderids and not order.is_active():
|
if order.vt_orderid in vt_orderids and not order.is_active():
|
||||||
@ -388,11 +393,16 @@ class CtaEngine(BaseEngine):
|
|||||||
|
|
||||||
strategy = self.orderid_strategy_map.get(trade.vt_orderid, None)
|
strategy = self.orderid_strategy_map.get(trade.vt_orderid, None)
|
||||||
if not strategy:
|
if not strategy:
|
||||||
self.write_log(f'成交单没有对应的策略设置:trade:{trade.__dict__}')
|
if trade.sys_orderid and trade.sys_orderid in self.orderid_strategy_map:
|
||||||
self.write_log(f'当前策略侦听委托单:{list(self.orderid_strategy_map.keys())}')
|
self.write_log(f'使用系统委托单号{trade.sys_orderid} => 策略')
|
||||||
return
|
strategy = self.orderid_strategy_map.get(trade.sys_orderid, None)
|
||||||
|
|
||||||
self.write_log(f'成交更新:{trade.vt_orderid} => 策略:{strategy.strategy_name}')
|
if not strategy:
|
||||||
|
self.write_log(f'成交单没有对应的策略设置:trade:{trade.__dict__}')
|
||||||
|
self.write_log(f'当前策略侦听委托单:{list(self.orderid_strategy_map.keys())}')
|
||||||
|
return
|
||||||
|
|
||||||
|
self.write_log(f'成交更新,本地委托{trade.vt_orderid},系统委托{trade.sys_orderid} => 策略:{strategy.strategy_name}')
|
||||||
|
|
||||||
# Update strategy pos before calling on_trade method
|
# Update strategy pos before calling on_trade method
|
||||||
# 取消外部干预策略pos,由策略自行完成更新
|
# 取消外部干预策略pos,由策略自行完成更新
|
||||||
|
@ -425,6 +425,14 @@ class BackTestingEngine(object):
|
|||||||
@lru_cache()
|
@lru_cache()
|
||||||
def get_size(self, vt_symbol: str):
|
def get_size(self, vt_symbol: str):
|
||||||
"""查询合约的size"""
|
"""查询合约的size"""
|
||||||
|
if vt_symbol not in self.size:
|
||||||
|
symbol, exchange = extract_vt_symbol(vt_symbol)
|
||||||
|
if symbol in self.size:
|
||||||
|
return self.size.get(symbol)
|
||||||
|
else:
|
||||||
|
underly_symbol = get_underlying_symbol(symbol).upper()
|
||||||
|
return self.size.get(f'{underly_symbol}99',10)
|
||||||
|
|
||||||
return self.size.get(vt_symbol, 10)
|
return self.size.get(vt_symbol, 10)
|
||||||
|
|
||||||
def set_price(self, vt_symbol: str, price: float):
|
def set_price(self, vt_symbol: str, price: float):
|
||||||
@ -440,11 +448,16 @@ class BackTestingEngine(object):
|
|||||||
if rate >= 0.1:
|
if rate >= 0.1:
|
||||||
self.fix_commission.update({vt_symbol: rate})
|
self.fix_commission.update({vt_symbol: rate})
|
||||||
|
|
||||||
|
@lru_cache()
|
||||||
def get_commission_rate(self, vt_symbol: str):
|
def get_commission_rate(self, vt_symbol: str):
|
||||||
""" 获取保证金比例,缺省万分之一"""
|
""" 获取保证金比例,缺省万分之一"""
|
||||||
if vt_symbol not in self.commission_rate:
|
if vt_symbol not in self.commission_rate:
|
||||||
symbol, exchange = extract_vt_symbol(vt_symbol)
|
symbol, exchange = extract_vt_symbol(vt_symbol)
|
||||||
return self.commission_rate.get(symbol, float(0.0001))
|
if symbol in self.commission_rate:
|
||||||
|
return self.commission_rate.get(symbol)
|
||||||
|
else:
|
||||||
|
underly_symbol = get_underlying_symbol(symbol).upper()
|
||||||
|
return self.commission_rate.get(f'{underly_symbol}99', float(0.0001))
|
||||||
return self.commission_rate.get(vt_symbol, float(0.0001))
|
return self.commission_rate.get(vt_symbol, float(0.0001))
|
||||||
|
|
||||||
def get_fix_commission(self, vt_symbol: str):
|
def get_fix_commission(self, vt_symbol: str):
|
||||||
@ -887,6 +900,16 @@ class BackTestingEngine(object):
|
|||||||
self.write_log(f"新增订阅指数合约:{setting['idx_symbol']}")
|
self.write_log(f"新增订阅指数合约:{setting['idx_symbol']}")
|
||||||
self.subscribe_symbol(strategy_name=strategy_name, vt_symbol=setting['idx_symbol'])
|
self.subscribe_symbol(strategy_name=strategy_name, vt_symbol=setting['idx_symbol'])
|
||||||
|
|
||||||
|
# 如果act_vt_symbol不再列表中,需要订阅
|
||||||
|
if 'act_vt_symbol' in setting.keys() and setting['act_vt_symbol'] not in self.symbol_strategy_map.keys():
|
||||||
|
self.write_log(f"新增订阅act_vt_symbol合约:{setting['act_vt_symbol']}")
|
||||||
|
self.subscribe_symbol(strategy_name=strategy_name, vt_symbol=setting['act_vt_symbol'])
|
||||||
|
|
||||||
|
# 如果pas_vt_symbol不再列表中,需要订阅
|
||||||
|
if 'pas_vt_symbol' in setting.keys() and setting['pas_vt_symbol'] not in self.symbol_strategy_map.keys():
|
||||||
|
self.write_log(f"新增订阅pas_vt_symbol合约:{setting['pas_vt_symbol']}")
|
||||||
|
self.subscribe_symbol(strategy_name=strategy_name, vt_symbol=setting['pas_vt_symbol'])
|
||||||
|
|
||||||
if strategy_setting.get('auto_init', False):
|
if strategy_setting.get('auto_init', False):
|
||||||
self.write_log(u'自动初始化策略')
|
self.write_log(u'自动初始化策略')
|
||||||
strategy.on_init()
|
strategy.on_init()
|
||||||
@ -1264,8 +1287,8 @@ class BackTestingEngine(object):
|
|||||||
target=self.get_price_tick(vt_symbol)) - self.get_price_tick(
|
target=self.get_price_tick(vt_symbol)) - self.get_price_tick(
|
||||||
vt_symbol) # 在当前时间点前发出的卖出委托可能的最优成交价
|
vt_symbol) # 在当前时间点前发出的卖出委托可能的最优成交价
|
||||||
else:
|
else:
|
||||||
buy_cross_price = tick.last_price
|
buy_cross_price = tick.last_price if not tick.ask_price_1 else tick.ask_price_1
|
||||||
sell_cross_price = tick.last_price
|
sell_cross_price = tick.last_price if not tick.bid_price_1 else tick.bid_price_1
|
||||||
buy_best_cross_price = tick.last_price
|
buy_best_cross_price = tick.last_price
|
||||||
sell_best_cross_price = tick.last_price
|
sell_best_cross_price = tick.last_price
|
||||||
|
|
||||||
@ -2317,6 +2340,8 @@ class BackTestingEngine(object):
|
|||||||
|
|
||||||
result_info.update({u'Sharpe Ratio': d['sharpe']})
|
result_info.update({u'Sharpe Ratio': d['sharpe']})
|
||||||
self.output(u'Sharpe Ratio:\t%s' % format_number(d['sharpe']))
|
self.output(u'Sharpe Ratio:\t%s' % format_number(d['sharpe']))
|
||||||
|
result_file = os.path.abspath(os.path.join(self.get_logs_path(), '{}_result.csv'.format(self.test_name)))
|
||||||
|
self.append_data(result_file, result_info)
|
||||||
|
|
||||||
# 保存回测结果/交易记录/日线统计 至数据库
|
# 保存回测结果/交易记录/日线统计 至数据库
|
||||||
self.save_result_to_mongo(result_info)
|
self.save_result_to_mongo(result_info)
|
||||||
|
@ -419,9 +419,9 @@ class CtaSpreadTemplate(CtaTemplate):
|
|||||||
if order_info is not None:
|
if order_info is not None:
|
||||||
# 委托单记录 =》 找到 Grid
|
# 委托单记录 =》 找到 Grid
|
||||||
grid = order_info.get('grid')
|
grid = order_info.get('grid')
|
||||||
if grid and order_info.get('offset', None) == Offset.OPEN:
|
if grid :
|
||||||
# 更新平均开仓/平仓得价格,数量
|
# 更新平均开仓/平仓得价格,数量
|
||||||
self.update_grid_trade(trade, grid)
|
self.update_grid_trade(order_info.get('offset', None), trade, grid)
|
||||||
|
|
||||||
def update_pos(self, price, volume, operation, dt):
|
def update_pos(self, price, volume, operation, dt):
|
||||||
"""更新持仓组件得pos"""
|
"""更新持仓组件得pos"""
|
||||||
@ -535,14 +535,14 @@ class CtaSpreadTemplate(CtaTemplate):
|
|||||||
"""修正order被拆单得情况"""
|
"""修正order被拆单得情况"""
|
||||||
order_info = self.active_orders.get(order.vt_orderid, None)
|
order_info = self.active_orders.get(order.vt_orderid, None)
|
||||||
if order_info:
|
if order_info:
|
||||||
volume = order_info.get('volume')
|
volume = order_info.get('volume') # 原始委托数量
|
||||||
traded = order_info.get('traded')
|
traded = order_info.get('traded') # 原始委托中,已成交的数量
|
||||||
if volume != order.volume:
|
if volume != order.volume:
|
||||||
self.write_log(f'调整{order.vt_orderid} {order.vt_symbol} 委托:{volume}=>{order.volume}')
|
self.write_log(f'更新未完成订单{order.vt_orderid} {order.vt_symbol} 的委托数量:{volume}=>{order.volume}')
|
||||||
order_info.update({'volume': order.volume})
|
order_info.update({'volume': order.volume})
|
||||||
if traded != order.traded:
|
if traded != order.traded:
|
||||||
self.write_log(f'{order.vt_orderid} {order.vt_symbol} 已成交 :{traded}=>{traded + order.traded}')
|
self.write_log(f'更新未完成订单{order.vt_orderid} {order.vt_symbol} 的已成交数量 :{traded}=>{traded + order.traded}')
|
||||||
order_info.update({'volume': traded + order.traded})
|
order_info.update({'traded': traded + order.traded})
|
||||||
|
|
||||||
def on_order(self, order: OrderData):
|
def on_order(self, order: OrderData):
|
||||||
"""报单更新"""
|
"""报单更新"""
|
||||||
@ -582,9 +582,9 @@ class CtaSpreadTemplate(CtaTemplate):
|
|||||||
else:
|
else:
|
||||||
self.write_error(u'委托单{}不在策略的未完成订单列表中:{}'.format(order.vt_orderid, self.active_orders))
|
self.write_error(u'委托单{}不在策略的未完成订单列表中:{}'.format(order.vt_orderid, self.active_orders))
|
||||||
|
|
||||||
def update_grid_trade(self, trade: TradeData, grid: CtaGrid):
|
def update_grid_trade(self, offset: Offset, trade: TradeData, grid: CtaGrid):
|
||||||
"""更新网格内,主动腿/被动腿得开平仓信息"""
|
"""更新网格内,主动腿/被动腿得开平仓信息"""
|
||||||
if trade.offset == Offset.OPEN:
|
if offset == Offset.OPEN:
|
||||||
# 更新开仓均价/数量
|
# 更新开仓均价/数量
|
||||||
if trade.vt_symbol == self.act_vt_symbol:
|
if trade.vt_symbol == self.act_vt_symbol:
|
||||||
opened_price = grid.snapshot.get('act_open_price', 0)
|
opened_price = grid.snapshot.get('act_open_price', 0)
|
||||||
@ -660,7 +660,7 @@ class CtaSpreadTemplate(CtaTemplate):
|
|||||||
grid.traded_volume = 0
|
grid.traded_volume = 0
|
||||||
|
|
||||||
# 平仓完毕(cover, sell)
|
# 平仓完毕(cover, sell)
|
||||||
if order.offset != Offset.OPEN:
|
if order_info.get("offset", None) != Offset.OPEN:
|
||||||
grid.open_status = False
|
grid.open_status = False
|
||||||
grid.close_status = True
|
grid.close_status = True
|
||||||
|
|
||||||
|
@ -2496,7 +2496,10 @@ class CtaLineBar(object):
|
|||||||
def __count_ama(self):
|
def __count_ama(self):
|
||||||
"""计算K线的卡夫曼自适应AMA1
|
"""计算K线的卡夫曼自适应AMA1
|
||||||
如何测量价格变动的速率。
|
如何测量价格变动的速率。
|
||||||
采用的方法是,在一定的周期内,计算每个周期价格的变动的累加,用整个周期的总体价格变动除以每个周期价格变动的累加,我们采用这个数字作为价格变化的速率。如果股票持续上涨或下跌,那么变动的速率就是1;如果股票在一定周期内涨跌的幅度为0,那么价格的变动速率就是0。变动速率为1,对应的最快速的均线-2日的EMA;变动速率为0 ,则对应最慢速的均线-30日EMA。
|
采用的方法是,在一定的周期内,计算每个周期价格的变动的累加,用整个周期的总体价格变动除以每个周期价格变动的累加,
|
||||||
|
我们采用这个数字作为价格变化的速率。如果股票持续上涨或下跌,那么变动的速率就是1;
|
||||||
|
如果股票在一定周期内涨跌的幅度为0,那么价格的变动速率就是0。变动速率为1,
|
||||||
|
对应的最快速的均线-2日的EMA;变动速率为0 ,则对应最慢速的均线-30日EMA。
|
||||||
以通达信软件的公式为例(其他软件也可以用):
|
以通达信软件的公式为例(其他软件也可以用):
|
||||||
每个周期价格变动的累加:=sum(abs(close-ref(close,1)),n);
|
每个周期价格变动的累加:=sum(abs(close-ref(close,1)),n);
|
||||||
整个周期价格的总体变动:=abs(close-ref(close,n));
|
整个周期价格的总体变动:=abs(close-ref(close,n));
|
||||||
|
@ -6,15 +6,31 @@
|
|||||||
# 2. 下载tick时,5档行情都下载
|
# 2. 下载tick时,5档行情都下载
|
||||||
# 3. 五档行情变量调整适合vnpy的命名方式
|
# 3. 五档行情变量调整适合vnpy的命名方式
|
||||||
|
|
||||||
|
import os
|
||||||
import csv
|
import csv
|
||||||
from datetime import date, datetime
|
from datetime import date, datetime
|
||||||
from typing import Union, List
|
from typing import Union, List
|
||||||
|
import json
|
||||||
from tqsdk.api import TqApi
|
from tqsdk.api import TqApi
|
||||||
from tqsdk.datetime import _get_trading_day_start_time, _get_trading_day_end_time
|
from tqsdk.datetime import _get_trading_day_start_time, _get_trading_day_end_time
|
||||||
from tqsdk.diff import _get_obj
|
from tqsdk.diff import _get_obj
|
||||||
from tqsdk.utils import _generate_uuid
|
from tqsdk.utils import _generate_uuid
|
||||||
|
|
||||||
|
def get_account_config():
|
||||||
|
"""
|
||||||
|
获取本地账号配置
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
config_file_name = os.path.abspath(os.path.join(os.path.dirname(__file__), 'auth_account.json'))
|
||||||
|
if os.path.exists(config_file_name):
|
||||||
|
try:
|
||||||
|
with open(config_file_name, mode="r", encoding="UTF-8") as f:
|
||||||
|
data = json.load(f)
|
||||||
|
return data
|
||||||
|
except Exception as ex:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return {}
|
||||||
|
|
||||||
class DataDownloader:
|
class DataDownloader:
|
||||||
"""
|
"""
|
||||||
|
@ -792,8 +792,6 @@ class LocalOrderManager:
|
|||||||
Keep an order buf before pushing it to gateway.
|
Keep an order buf before pushing it to gateway.
|
||||||
"""
|
"""
|
||||||
self.orders[order.orderid] = copy(order)
|
self.orders[order.orderid] = copy(order)
|
||||||
|
|
||||||
|
|
||||||
self.gateway.on_order(order)
|
self.gateway.on_order(order)
|
||||||
|
|
||||||
def cancel_order(self, req: CancelRequest) -> None:
|
def cancel_order(self, req: CancelRequest) -> None:
|
||||||
|
Loading…
Reference in New Issue
Block a user