[update] 选股脚本、每天下载复权因子、股票引擎更新、期货品种更新
This commit is contained in:
parent
6e4f739713
commit
58f388e67b
21
README.md
21
README.md
@ -10,6 +10,14 @@ github 链接: https://github.com/msincenselee/vnpy
|
||||
gitee 链接: https://gitee.com/vnpy2/vnpy
|
||||
|
||||
###Fork版本主要改进如下
|
||||
|
||||
18、CTA股票选股引擎
|
||||
|
||||
-vnpy.app.stock_screener
|
||||
+ 无界面选股引擎
|
||||
-prod.screener_d1
|
||||
+ 每日执行一次选股所有选股策略脚本
|
||||
|
||||
17、东财股票接入
|
||||
|
||||
- vnpy.api.eastmoney_api,
|
||||
@ -153,10 +161,15 @@ gitee 链接: https://gitee.com/vnpy2/vnpy
|
||||
大佳
|
||||
QQ/Wechat:28888502
|
||||
|
||||
2021 股票CTA实战课程:http://www.uquant.org/course/49
|
||||
2021 期货缠论高级课程:http://www.uquant.org/course/48
|
||||
2021 数字货币CTA课程:http://www.uquant.org/course/46
|
||||
2020 期货套利课程:http://www.uquant.org/course/43
|
||||
系列在线课程
|
||||
|
||||
2021 股票CTA实战课程:http://www.uquant.org/course/49
|
||||
|
||||
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的开源交易平台开发框架
|
||||
|
21
prod/jobs/daily_download_stock_adjust_factors.sh
Normal file
21
prod/jobs/daily_download_stock_adjust_factors.sh
Normal 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
|
||||
|
||||
|
||||
|
@ -29,7 +29,7 @@ if VNPY_ROOT not in sys.path:
|
||||
|
||||
os.environ["VNPY_TESTING"] = "1"
|
||||
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
|
||||
|
||||
if __name__ == "__main__":
|
||||
@ -38,6 +38,9 @@ if __name__ == "__main__":
|
||||
print(u'请输入:{}目录下的子目录作为参数1'.format(os.path.abspath(os.path.join(VNPY_ROOT, 'prod'))))
|
||||
exit()
|
||||
|
||||
print('下载更新所有复权因子')
|
||||
download_adjust_factor()
|
||||
|
||||
# 进行报告的账号目录
|
||||
account_folder = sys.argv[1]
|
||||
account_folder = os.path.abspath(os.path.join(VNPY_ROOT, 'prod', account_folder))
|
||||
|
5
prod/screener_d1/readme.md
Normal file
5
prod/screener_d1/readme.md
Normal file
@ -0,0 +1,5 @@
|
||||
日线选股
|
||||
|
||||
配置选股策略文件 screenr_setting.json
|
||||
|
||||
定时任务运行 run_screener.py
|
115
prod/screener_d1/run_screener.py
Normal file
115
prod/screener_d1/run_screener.py
Normal 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()
|
14
prod/screener_d1/screener_setting.json
Normal file
14
prod/screener_d1/screener_setting.json
Normal 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"
|
||||
}
|
||||
}
|
||||
}
|
@ -1274,38 +1274,47 @@ class CtaEngine(BaseEngine):
|
||||
"""
|
||||
Add a new strategy.
|
||||
"""
|
||||
if strategy_name in self.strategies:
|
||||
msg = f"创建策略失败,存在重名{strategy_name}"
|
||||
self.write_log(msg=msg,
|
||||
level=logging.CRITICAL)
|
||||
return False, msg
|
||||
try:
|
||||
if strategy_name in self.strategies:
|
||||
msg = f"创建策略失败,存在重名{strategy_name}"
|
||||
self.write_log(msg=msg,
|
||||
level=logging.CRITICAL)
|
||||
return False, msg
|
||||
|
||||
strategy_class = self.classes.get(class_name, None)
|
||||
if not strategy_class:
|
||||
msg = f"创建策略失败,找不到策略类{class_name}"
|
||||
self.write_log(msg=msg,
|
||||
level=logging.CRITICAL)
|
||||
return False, msg
|
||||
strategy_class = self.classes.get(class_name, None)
|
||||
if not strategy_class:
|
||||
msg = f"创建策略失败,找不到策略类{class_name}"
|
||||
self.write_log(msg=msg,
|
||||
level=logging.CRITICAL)
|
||||
return False, msg
|
||||
|
||||
self.write_log(f'开始添加策略类{class_name},实例名:{strategy_name}')
|
||||
strategy = strategy_class(self, strategy_name, vt_symbols, setting)
|
||||
self.strategies[strategy_name] = strategy
|
||||
self.write_log(f'开始添加策略类{class_name},实例名:{strategy_name}')
|
||||
strategy = strategy_class(self, strategy_name, vt_symbols, setting)
|
||||
self.strategies[strategy_name] = strategy
|
||||
|
||||
# Add vt_symbol to strategy map.
|
||||
subscribe_symbol_set = self.strategy_symbol_map[strategy_name]
|
||||
for vt_symbol in vt_symbols:
|
||||
strategies = self.symbol_strategy_map[vt_symbol]
|
||||
strategies.append(strategy)
|
||||
subscribe_symbol_set.add(vt_symbol)
|
||||
# Add vt_symbol to strategy map.
|
||||
subscribe_symbol_set = self.strategy_symbol_map[strategy_name]
|
||||
for vt_symbol in vt_symbols:
|
||||
strategies = self.symbol_strategy_map[vt_symbol]
|
||||
strategies.append(strategy)
|
||||
subscribe_symbol_set.add(vt_symbol)
|
||||
|
||||
# Update to setting file.
|
||||
self.update_strategy_setting(strategy_name, setting, auto_init, auto_start)
|
||||
# Update to setting file.
|
||||
self.update_strategy_setting(strategy_name, setting, auto_init, auto_start)
|
||||
|
||||
self.put_strategy_event(strategy)
|
||||
self.put_strategy_event(strategy)
|
||||
|
||||
# 判断设置中是否由自动初始化和自动启动项目
|
||||
if auto_init:
|
||||
self.init_strategy(strategy_name, auto_start=auto_start)
|
||||
# 判断设置中是否由自动初始化和自动启动项目
|
||||
if auto_init:
|
||||
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}'
|
||||
|
||||
@ -1497,15 +1506,19 @@ class CtaEngine(BaseEngine):
|
||||
if module_name:
|
||||
new_class_name = module_name + '.' + 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)
|
||||
if strategy_class is None:
|
||||
err_msg = u'加载策略模块失败:{}'.format(class_name)
|
||||
err_msg = u'加载策略模块失败:{}'.format(new_class_name)
|
||||
self.write_error(err_msg)
|
||||
return False, err_msg
|
||||
|
||||
self.write_log(f'重新加载模块成功,使用新模块:{new_class_name}')
|
||||
self.write_log(f'新策略ID:{id(strategy_class)}')
|
||||
self.classes[class_name] = strategy_class
|
||||
else:
|
||||
self.write_log(f'没有{class_name}的module_name,无法重新加载模块')
|
||||
|
||||
# 停止当前策略实例的运行,撤单
|
||||
self.stop_strategy(strategy_name)
|
||||
|
@ -1,4 +1,6 @@
|
||||
""""""
|
||||
# 股票模板
|
||||
# 华富资产 @ 李来佳
|
||||
|
||||
import os
|
||||
import sys
|
||||
import uuid
|
||||
@ -38,7 +40,7 @@ class CtaTemplate(ABC):
|
||||
self,
|
||||
cta_engine: Any,
|
||||
strategy_name: str,
|
||||
vt_symbols: List[str],
|
||||
vt_symbols: str,
|
||||
setting: dict,
|
||||
):
|
||||
""""""
|
||||
@ -204,6 +206,9 @@ class CtaTemplate(ABC):
|
||||
if self.is_upper_limit(vt_symbol):
|
||||
self.write_error(u'涨停价不做FAK/FOK委托')
|
||||
return []
|
||||
if volume == 0:
|
||||
self.write_error(f'委托数量有误,必须大于0,{vt_symbol}, price:{price}')
|
||||
return []
|
||||
return self.send_order(vt_symbol=vt_symbol,
|
||||
direction=Direction.LONG,
|
||||
offset=Offset.OPEN,
|
||||
@ -224,6 +229,9 @@ class CtaTemplate(ABC):
|
||||
if self.is_lower_limit(vt_symbol):
|
||||
self.write_error(u'跌停价不做FAK/FOK sell委托')
|
||||
return []
|
||||
if volume == 0:
|
||||
self.write_error(f'委托数量有误,必须大于0,{vt_symbol}, price:{price}')
|
||||
return []
|
||||
return self.send_order(vt_symbol=vt_symbol,
|
||||
direction=Direction.SHORT,
|
||||
offset=Offset.CLOSE,
|
||||
@ -253,6 +261,7 @@ class CtaTemplate(ABC):
|
||||
return []
|
||||
|
||||
if not self.trading:
|
||||
self.write_log(f'非交易状态')
|
||||
return []
|
||||
|
||||
vt_orderids = self.cta_engine.send_order(
|
||||
|
@ -132,7 +132,7 @@ def download_adjust_factor():
|
||||
if __name__ == '__main__':
|
||||
|
||||
# 下载所有复权数据
|
||||
# download_adjust_factor()
|
||||
download_adjust_factor()
|
||||
|
||||
# 下载某个股票的复权数据
|
||||
# f = get_adjust_factor(vt_symbol='000651.SZSE',stock_name='格力电器',need_login=True)
|
||||
|
@ -70,7 +70,8 @@ INIT_TDX_MARKET_MAP = {
|
||||
'CJL9': 28, 'CYL9': 28, 'FGL9': 28, 'JRL9': 28, 'LRL9': 28, 'MAL9': 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,
|
||||
'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
|
||||
ALL_MARKET_BEGIN_HOUR = 8
|
||||
|
Loading…
Reference in New Issue
Block a user