forked from waditu/czsc
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
1,143 additions
and
0 deletions.
There are no files selected for viewing
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
# -*- coding: utf-8 -*- | ||
""" | ||
author: zengbin93 | ||
email: [email protected] | ||
create_dt: 2021/6/28 22:11 | ||
""" | ||
|
||
from scripts_gm.gm_utils import * | ||
|
||
# ct = GmCzscTrader("SZSE.002414", end_dt='2021-06-25 14:38:00+08:00') | ||
ct = GmCzscTrader("SZSE.002414", end_dt='2021-06-25 14:38:00+08:00') | ||
ct.open_in_browser() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
# coding: utf-8 | ||
import inspect | ||
from czsc.analyze import * | ||
from czsc.utils.log import create_logger | ||
from scripts_gm.gm_utils import * | ||
from scripts_gm.strategy import get_signals_share_f15_v1 as get_user_signals | ||
from scripts_gm.strategy import get_events_share_f15_v1 as get_user_events | ||
from scripts_gm.strategy import freqs_share_f15_v1 as user_freqs | ||
|
||
|
||
def adjust_position(context, symbol): | ||
bars = context.data(symbol=symbol, frequency='60s', count=100, fields='symbol,eob,open,close,high,low,volume') | ||
trader: CzscTrader = context.symbols_map[symbol]['trader'] | ||
mp = context.symbols_map[symbol]['mp'] | ||
bars = format_kline(bars, freq=Freq.F1) | ||
bars_new = [x for x in bars if x.dt > trader.kg.end_dt] | ||
if bars_new: | ||
for k in bars_new: | ||
trader.check_operate(k, context.stoploss, context.timeout) | ||
context.symbols_map[symbol]['trader'] = trader | ||
last_bar = bars[-1] | ||
if last_bar.dt.minute % 30 == 0: | ||
print(trader.op) | ||
|
||
exchange = symbol.split(".")[0] | ||
if exchange in ["SZSE", "SHSE"]: | ||
adjust_share_position(context, symbol, trader, mp) | ||
else: | ||
adjust_future_position(context, symbol, trader, mp) | ||
|
||
|
||
def init(context): | ||
data_path = "C:/gm_logs/1min_{}".format(datetime.now().strftime("%Y_%m_%d_%H_%M_%S")) | ||
|
||
# 填写企业微信群聊机器人的 key,会发送消息到对应企业微信群聊 | ||
context.wx_key = "2daec96b-f3f1-****-****-2952fe2731c0" | ||
|
||
cache_path = os.path.join(data_path, "cache") | ||
os.makedirs(cache_path, exist_ok=False) | ||
context.logger = create_logger(os.path.join(data_path, "backtest.log"), cmd=True, name="gm") | ||
context.data_path = data_path | ||
context.cache_path = cache_path | ||
context.file_orders = os.path.join(data_path, "orders.txt") | ||
|
||
context.stoploss = 0.05 # 止损条件设定 | ||
context.timeout = 600 # 超时条件设定 | ||
|
||
# 仓位控制[0, 1],按资金百分比控制,1表示满仓,仅在开仓的时候控制 | ||
context.max_total_position = 0.3 | ||
context.max_share_position = 0.3 | ||
assert 0 <= context.max_total_position <= 1 | ||
assert 0 <= context.max_share_position <= 1 | ||
assert context.max_total_position >= context.max_share_position >= 0 | ||
|
||
context.logger.info("回测配置:") | ||
context.logger.info("backtest_start_time = " + str(context.backtest_start_time)) | ||
context.logger.info("backtest_end_time = " + str(context.backtest_end_time)) | ||
context.logger.info(f"异常退出条件:stoploss = {context.stoploss}; timeout = {context.timeout}") | ||
context.logger.info("交易使用的信号定义如下:\n" + inspect.getsource(get_user_signals)) | ||
context.logger.info("交易使用的买卖点定义如下:\n" + inspect.getsource(get_user_events)) | ||
|
||
symbols = [ | ||
'SHSE.510500', | ||
'SZSE.300014', | ||
'SHSE.600143' | ||
] | ||
context.logger.info(f"交易标的数量:{len(symbols)}") | ||
|
||
symbols_map = {symbol: dict() for symbol in symbols} | ||
for symbol in symbols: | ||
try: | ||
symbols_map[symbol]['mp'] = context.max_share_position | ||
kg = get_init_kg(symbol, context.now, max_count=2000, adjust=ADJUST_POST, freqs=user_freqs) | ||
trader = CzscTrader(kg, get_signals=get_user_signals, events=get_user_events()) | ||
symbols_map[symbol]['trader'] = trader | ||
context.logger.info("{} 初始化完成,当前时间:{}".format(symbol, trader.end_dt)) | ||
except: | ||
traceback.print_exc() | ||
context.logger.info("{} 初始化失败".format(symbol)) | ||
|
||
subscribe(",".join(symbols_map.keys()), frequency='60s', count=300, wait_group=True) | ||
context.logger.info(f"交易标的配置:{symbols_map}") | ||
context.symbols_map = symbols_map | ||
|
||
|
||
def on_bar(context, bars): | ||
context.unfinished_orders = get_unfinished_orders() | ||
|
||
for bar in bars: | ||
symbol = bar['symbol'] | ||
try: | ||
adjust_position(context, symbol) | ||
except: | ||
traceback.print_exc() | ||
|
||
if context.now.hour == 13 and context.now.minute == 59: | ||
report_account_status(context) | ||
|
||
|
||
if __name__ == '__main__': | ||
run(filename='gm_backtest_1min.py', token=gm_token, | ||
strategy_id='692dc7b5-d19f-11eb-af0a-38f3abf8ed06', | ||
mode=MODE_BACKTEST, | ||
backtest_start_time='2020-01-06 14:30:00', | ||
backtest_end_time='2020-12-31 15:30:00', | ||
backtest_initial_cash=100000000, | ||
backtest_transaction_ratio=1, | ||
backtest_commission_ratio=0.001, | ||
backtest_slippage_ratio=0.0005, | ||
backtest_adjust=ADJUST_POST, | ||
backtest_check_cache=1) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
# coding: utf-8 | ||
import numpy as np | ||
from tqdm import tqdm | ||
from czsc.utils.ta import SMA | ||
from czsc.analyze import * | ||
from scripts_gm.gm_utils import * | ||
|
||
|
||
def is_up_gap(bars: List[RawBar]): | ||
"""判断 bars 中是否有向上跳空缺口不补事件出现 | ||
:param bars: | ||
:return: | ||
""" | ||
ma5 = SMA(np.array([x.close for x in bars]), timeperiod=5) | ||
|
||
# 收盘价跌破 MA5 是不允许的 | ||
if bars[-1].close < ma5[-1]: | ||
return False | ||
|
||
max_id = bars[-1].id | ||
for i in [4, 3, 2, 1]: # 近五个K线中找缺口 | ||
bar1 = bars[max_id-i-1] | ||
bar2 = bars[max_id-i] | ||
max_high = max([x.high for x in bars[:max_id-i-1]]) | ||
|
||
# 缺口创新高 | ||
if bar2.high > max_high > bar1.high and bar2.low > bar1.high: | ||
qid = max_id - i | ||
p_high = bar1.high | ||
after_q = [x for x in bars if x.id >= qid] | ||
|
||
if min([x.low for x in after_q]) > p_high \ | ||
and after_q[0].close > after_q[-1].low: | ||
return True | ||
else: | ||
return False | ||
|
||
return False | ||
|
||
def is_up_big(bars: List[RawBar]): | ||
"""判断 bars 中是否有光头阳线突破不补事件出现 | ||
:param bars: | ||
:return: | ||
""" | ||
ma5 = SMA(np.array([x.close for x in bars]), timeperiod=5) | ||
|
||
# 收盘价跌破 MA5 是不允许的 | ||
if bars[-1].close < ma5[-1]: | ||
return False | ||
|
||
max_id = bars[-1].id | ||
for i in [5, 4, 3, 2]: # 最近K线中找光头阳线 | ||
bar = bars[max_id - i] | ||
max_high = max([x.high for x in bars[:max_id-i-1]]) | ||
# 光头大阳线定义:1)涨幅超过7个点;2)开盘价不高于最低价一个点;3)收盘价不低于最高价0.5个点 | ||
if bar.open < bar.low * 1.01 and bar.close < bar.high * 0.995 and (bar.close - bar.open) / bar.open > 0.07: | ||
qid = max_id - i | ||
after_q = [x for x in bars if x.id > qid] | ||
|
||
# 三买验证:1)光头阳线创新高;2)新高后的走势不跌破光头阳线的实体中部;3)在光头阳线后一根K线价格范围盘整 | ||
if bar.high > max_high \ | ||
and min([x.low for x in after_q]) > bar.open + (bar.close - bar.open) / 2 \ | ||
and after_q[0].close > after_q[-1].low: | ||
return True | ||
else: | ||
return False | ||
|
||
return False | ||
|
||
|
||
def run_selector(context=None, end_date: [str, datetime] = datetime.now()): | ||
key = context.wx_key | ||
symbols = get_index_shares('上证指数') | ||
if isinstance(end_date, str): | ||
end_date = pd.to_datetime(end_date) | ||
push_text(content="start running selector", key=key) | ||
for symbol in tqdm(symbols, desc=f"{end_date}"): | ||
try: | ||
count = 30 | ||
k0 = get_kline(symbol, end_time=end_date, freq='1d', count=count, adjust=ADJUST_PREV) | ||
print("\n", k0[-1]) | ||
if len(k0) != count: | ||
continue | ||
|
||
last_vols = [k_.open * k_.vol for k_ in k0[-10:]] | ||
if sum(last_vols) < 1e9: | ||
print(f"{symbol} 近10个交易日累计成交金额小于10亿") | ||
continue | ||
if min(last_vols) < 5e7: | ||
print(f"{symbol} 近10个交易日最低成交额小于5000万") | ||
continue | ||
|
||
if is_up_gap(k0): | ||
msg = f"symbol: {symbol}\nreason: 日线跳空创新高" | ||
push_text(content=msg, key=key) | ||
elif is_up_big(k0): | ||
msg = f"symbol: {symbol}\nreason: 日线光大阳突破" | ||
push_text(content=msg, key=key) | ||
except: | ||
print("fail on {}".format(symbol)) | ||
traceback.print_exc() | ||
push_text(content="end running selector", key=key) | ||
|
||
|
||
if __name__ == '__main__': | ||
run_selector() | ||
|
||
|
Oops, something went wrong.