[update] 选股脚本、每天下载复权因子、股票引擎更新、期货品种更新

This commit is contained in:
msincenselee 2021-11-14 00:24:44 +08:00
parent 6e4f739713
commit 58f388e67b
10 changed files with 231 additions and 37 deletions

View File

@ -10,6 +10,14 @@ github 链接: https://github.com/msincenselee/vnpy
gitee 链接: https://gitee.com/vnpy2/vnpy gitee 链接: https://gitee.com/vnpy2/vnpy
###Fork版本主要改进如下 ###Fork版本主要改进如下
18、CTA股票选股引擎
-vnpy.app.stock_screener
+ 无界面选股引擎
-prod.screener_d1
+ 每日执行一次选股所有选股策略脚本
17、东财股票接入 17、东财股票接入
- vnpy.api.eastmoney_api, - vnpy.api.eastmoney_api,
@ -153,10 +161,15 @@ gitee 链接: https://gitee.com/vnpy2/vnpy
大佳 大佳
QQ/Wechat28888502 QQ/Wechat28888502
2021 股票CTA实战课程http://www.uquant.org/course/49 系列在线课程
2021 期货缠论高级课程http://www.uquant.org/course/48
2021 数字货币CTA课程http://www.uquant.org/course/46 2021 股票CTA实战课程http://www.uquant.org/course/49
2020 期货套利课程http://www.uquant.org/course/43
2021 期货缠论高级课程http://www.uquant.org/course/48
2021 数字货币CTA课程http://www.uquant.org/course/46
2020 期货套利课程http://www.uquant.org/course/43
-------------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------------
# 原版 vn.py - 基于python的开源交易平台开发框架 # 原版 vn.py - 基于python的开源交易平台开发框架

View File

@ -0,0 +1,21 @@
#!/bin/bash
CONDA_HOME=~/anaconda3
#$CONDA_HOME/bin/conda deactivate
#$CONDA_HOME/bin/conda activate py37
############ Added by Huang Jianwei at 2018-04-03
# To solve the problem about Javascript runtime
export PATH=$PATH:/usr/local/bin
############ Ended
BASE_PATH=$(cd `dirname $0`; pwd)
echo $BASE_PATH
cd `dirname $0`
PROGRAM_NAME=../../vnpy/data/stock/adjust_factor.py
# 全量下载baostock得复权因子
$CONDA_HOME/envs/py37/bin/python $PROGRAM_NAME

View File

@ -29,7 +29,7 @@ if VNPY_ROOT not in sys.path:
os.environ["VNPY_TESTING"] = "1" os.environ["VNPY_TESTING"] = "1"
from vnpy.trader.utility import load_json, save_json, append_data from vnpy.trader.utility import load_json, save_json, append_data
from vnpy.data.stock.adjust_factor import get_adjust_factor, get_stock_base from vnpy.data.stock.adjust_factor import download_adjust_factor, get_adjust_factor, get_stock_base
from vnpy.trader.util_wechat import send_wx_msg from vnpy.trader.util_wechat import send_wx_msg
if __name__ == "__main__": if __name__ == "__main__":
@ -38,6 +38,9 @@ if __name__ == "__main__":
print(u'请输入:{}目录下的子目录作为参数1'.format(os.path.abspath(os.path.join(VNPY_ROOT, 'prod')))) print(u'请输入:{}目录下的子目录作为参数1'.format(os.path.abspath(os.path.join(VNPY_ROOT, 'prod'))))
exit() exit()
print('下载更新所有复权因子')
download_adjust_factor()
# 进行报告的账号目录 # 进行报告的账号目录
account_folder = sys.argv[1] account_folder = sys.argv[1]
account_folder = os.path.abspath(os.path.join(VNPY_ROOT, 'prod', account_folder)) account_folder = os.path.abspath(os.path.join(VNPY_ROOT, 'prod', account_folder))

View File

@ -0,0 +1,5 @@
日线选股
配置选股策略文件 screenr_setting.json
定时任务运行 run_screener.py

View File

@ -0,0 +1,115 @@
# flake8: noqa
import os
import sys
import multiprocessing
from time import sleep
from datetime import datetime, time
from logging import DEBUG
# 将repostory的目录i作为根目录添加到系统环境中。
ROOT_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))
if ROOT_PATH not in sys.path:
sys.path.append(ROOT_PATH)
print(f'append {ROOT_PATH} into sys.path')
from vnpy.event import EventEngine, EVENT_TIMER
from vnpy.trader.setting import SETTINGS
from vnpy.trader.engine import MainEngine
from vnpy.trader.utility import load_json
# from vnpy.gateway.gj import GjGateway
from vnpy.app.stock_screener import ScreenerApp
# from vnpy.app.cta_stock import CtaStockApp
# from vnpy.app.cta_crypto.base import EVENT_CTA_LOG
from vnpy.app.rpc_service import RpcServiceApp
# from vnpy.app.algo_broker import AlgoBrokerApp
from vnpy.app.account_recorder import AccountRecorderApp
from vnpy.trader.util_pid import update_pid
# from vnpy.trader.util_monitor import OrderMonitor, TradeMonitor, PositionMonitor, AccountMonitor, LogMonitor
SETTINGS["log.active"] = True
SETTINGS["log.level"] = DEBUG
SETTINGS["log.console"] = True
SETTINGS["log.file"] = True
screener_name = '日线选股'
import types
import traceback
def excepthook(exctype: type, value: Exception, tb: types.TracebackType) -> None:
"""
Raise exception under debug mode
"""
sys.__excepthook__(exctype, value, tb)
msg = "".join(traceback.format_exception(exctype, value, tb))
print(msg, file=sys.stderr)
class DaemonService(object):
def __init__(self):
self.event_engine = EventEngine()
self.g_count = 0
self.last_dt = datetime.now()
# 创建主引擎
self.main_engine = MainEngine(self.event_engine)
self.save_data_time = None
self.save_snapshot_time = None
# 注册定时器,用于判断重连
self.event_engine.register(EVENT_TIMER, self.on_timer)
def on_timer(self, event):
"""定时器执行逻辑,每十秒执行一次"""
# 60秒才执行一次检查
self.g_count += 1
if self.g_count <= 60:
return
self.g_count = 0
dt = datetime.now()
# if dt.hour != self.last_dt.hour:
self.last_dt = dt
print(u'run_screener.py checkpoint:{0}'.format(dt))
self.main_engine.write_log(u'run_screener.py checkpoint:{0}'.format(dt))
if self.main_engine.get_all_completed_status():
from vnpy.trader.util_wechat import send_wx_msg
msg = f'{screener_name}完成所有选股任务'
send_wx_msg(content=msg)
self.main_engine.write_log(msg)
sleep(10)
os._exit(0)
def start(self):
"""
Running in the child process.
"""
SETTINGS["log.file"] = True
# 添加选股引擎
screen_engine = self.main_engine.add_app(ScreenerApp)
screen_engine.init_engine()
self.main_engine.write_log("主引擎创建成功")
while True:
sleep(1)
if __name__ == "__main__":
# from vnpy.trader.ui import create_qapp
# qApp = create_qapp()
# sys.excepthook = excepthook
s = DaemonService()
s.start()

View File

@ -0,0 +1,14 @@
{
"stock_screener_ThreeBuy_D1": {
"class_name": "StrategyChanlunThreeBuy",
"auto_init": true,
"auto_start": true,
"setting": {
"vt_symbols": [
"600410.SSE"
],
"all_stocks": false,
"bar_name": "D1"
}
}
}

View File

@ -1274,6 +1274,7 @@ class CtaEngine(BaseEngine):
""" """
Add a new strategy. Add a new strategy.
""" """
try:
if strategy_name in self.strategies: if strategy_name in self.strategies:
msg = f"创建策略失败,存在重名{strategy_name}" msg = f"创建策略失败,存在重名{strategy_name}"
self.write_log(msg=msg, self.write_log(msg=msg,
@ -1307,6 +1308,14 @@ class CtaEngine(BaseEngine):
if auto_init: if auto_init:
self.init_strategy(strategy_name, auto_start=auto_start) self.init_strategy(strategy_name, auto_start=auto_start)
except Exception as ex:
msg = f'添加策略实例{strategy_name}失败,{str(ex)}'
self.write_error(msg)
self.write_error(traceback.format_exc())
self.send_wechat(msg)
return False, f'添加策略实例{strategy_name}失败'
return True, f'成功添加{strategy_name}' return True, f'成功添加{strategy_name}'
def init_strategy(self, strategy_name: str, auto_start: bool = False): def init_strategy(self, strategy_name: str, auto_start: bool = False):
@ -1497,15 +1506,19 @@ class CtaEngine(BaseEngine):
if module_name: if module_name:
new_class_name = module_name + '.' + class_name new_class_name = module_name + '.' + class_name
self.write_log(u'转换策略为全路径:{}'.format(new_class_name)) self.write_log(u'转换策略为全路径:{}'.format(new_class_name))
old_strategy_class = self.classes[class_name]
self.write_log(f'旧策略ID:{id(old_strategy_class)}')
strategy_class = import_module_by_str(new_class_name) strategy_class = import_module_by_str(new_class_name)
if strategy_class is None: if strategy_class is None:
err_msg = u'加载策略模块失败:{}'.format(class_name) err_msg = u'加载策略模块失败:{}'.format(new_class_name)
self.write_error(err_msg) self.write_error(err_msg)
return False, err_msg return False, err_msg
self.write_log(f'重新加载模块成功,使用新模块:{new_class_name}') self.write_log(f'重新加载模块成功,使用新模块:{new_class_name}')
self.write_log(f'新策略ID:{id(strategy_class)}')
self.classes[class_name] = strategy_class self.classes[class_name] = strategy_class
else:
self.write_log(f'没有{class_name}的module_name,无法重新加载模块')
# 停止当前策略实例的运行,撤单 # 停止当前策略实例的运行,撤单
self.stop_strategy(strategy_name) self.stop_strategy(strategy_name)

View File

@ -1,4 +1,6 @@
"""""" # 股票模板
# 华富资产 @ 李来佳
import os import os
import sys import sys
import uuid import uuid
@ -38,7 +40,7 @@ class CtaTemplate(ABC):
self, self,
cta_engine: Any, cta_engine: Any,
strategy_name: str, strategy_name: str,
vt_symbols: List[str], vt_symbols: str,
setting: dict, setting: dict,
): ):
"""""" """"""
@ -204,6 +206,9 @@ class CtaTemplate(ABC):
if self.is_upper_limit(vt_symbol): if self.is_upper_limit(vt_symbol):
self.write_error(u'涨停价不做FAK/FOK委托') self.write_error(u'涨停价不做FAK/FOK委托')
return [] return []
if volume == 0:
self.write_error(f'委托数量有误必须大于0{vt_symbol}, price:{price}')
return []
return self.send_order(vt_symbol=vt_symbol, return self.send_order(vt_symbol=vt_symbol,
direction=Direction.LONG, direction=Direction.LONG,
offset=Offset.OPEN, offset=Offset.OPEN,
@ -224,6 +229,9 @@ class CtaTemplate(ABC):
if self.is_lower_limit(vt_symbol): if self.is_lower_limit(vt_symbol):
self.write_error(u'跌停价不做FAK/FOK sell委托') self.write_error(u'跌停价不做FAK/FOK sell委托')
return [] return []
if volume == 0:
self.write_error(f'委托数量有误必须大于0{vt_symbol}, price:{price}')
return []
return self.send_order(vt_symbol=vt_symbol, return self.send_order(vt_symbol=vt_symbol,
direction=Direction.SHORT, direction=Direction.SHORT,
offset=Offset.CLOSE, offset=Offset.CLOSE,
@ -253,6 +261,7 @@ class CtaTemplate(ABC):
return [] return []
if not self.trading: if not self.trading:
self.write_log(f'非交易状态')
return [] return []
vt_orderids = self.cta_engine.send_order( vt_orderids = self.cta_engine.send_order(

View File

@ -132,7 +132,7 @@ def download_adjust_factor():
if __name__ == '__main__': if __name__ == '__main__':
# 下载所有复权数据 # 下载所有复权数据
# download_adjust_factor() download_adjust_factor()
# 下载某个股票的复权数据 # 下载某个股票的复权数据
# f = get_adjust_factor(vt_symbol='000651.SZSE',stock_name='格力电器',need_login=True) # f = get_adjust_factor(vt_symbol='000651.SZSE',stock_name='格力电器',need_login=True)

View File

@ -70,7 +70,8 @@ INIT_TDX_MARKET_MAP = {
'CJL9': 28, 'CYL9': 28, 'FGL9': 28, 'JRL9': 28, 'LRL9': 28, 'MAL9': 28, 'CJL9': 28, 'CYL9': 28, 'FGL9': 28, 'JRL9': 28, 'LRL9': 28, 'MAL9': 28,
'OIL9': 28, 'PML9': 28, 'RIL9': 28, 'RML9': 28, 'RSL9': 28, 'SFL9': 28, 'OIL9': 28, 'PML9': 28, 'RIL9': 28, 'RML9': 28, 'RSL9': 28, 'SFL9': 28,
'SML9': 28, 'SRL9': 28, 'TAL9': 28, 'ICL9': 47, 'IFL9': 47, 'IHL9': 47, 'SML9': 28, 'SRL9': 28, 'TAL9': 28, 'ICL9': 47, 'IFL9': 47, 'IHL9': 47,
'TFL9': 47, 'TL9': 47, 'TSL9': 47, 'SAL9': 28, 'PGL9': 29, 'PFL9': 28, 'LH':29} 'TFL9': 47, 'TL9': 47, 'TSL9': 47, 'SAL9': 28, 'PGL9': 29, 'PFL9': 28,
'LHL9':29,'LUL9':30}
# 常量 # 常量
QSIZE = 500 QSIZE = 500
ALL_MARKET_BEGIN_HOUR = 8 ALL_MARKET_BEGIN_HOUR = 8