Skip to content

Commit

Permalink
V0.9.17 更新一批代码 (#143)
Browse files Browse the repository at this point in the history
* 0.9.17 修复绘图代码

* 0.9.17 更新信号

* 0.9.17 update

* 0.9.17 update

* 0.9.17 新增信号函数bar_dual_thrust_V230403

* 0.9.17 update

* 0.9.17 update

* 0.9.17 update

* 0.9.17 新增 未完成的笔 ubi 属性

* 0.9.17 新增策略中的信号检查函数

* 0.9.17 新增策略中的信号检查函数

* 0.9.17 新增基于 pos 的分型止损信号函数

* 0.9.17 优化MACD缓存方法

* 0.9.17 update
  • Loading branch information
zengbin93 authored Apr 16, 2023
1 parent 0ceb258 commit 5024ebb
Show file tree
Hide file tree
Showing 21 changed files with 608 additions and 328 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/pythonpackage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ name: Python package

on:
push:
branches: [ master, V0.9.16 ]
branches: [ master, V0.9.17 ]
pull_request:
branches: [ master ]

Expand All @@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.7, 3.8, 3.9, 3.10.10, 3.11.2]
python-version: [3.7, 3.8, 3.9, 3.10.11, 3.11.3]

steps:
- uses: actions/checkout@v2
Expand Down
6 changes: 3 additions & 3 deletions czsc/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@
from czsc.strategies import CzscStrategyBase
from czsc.utils import KlineChart, BarGenerator, resample_bars, dill_dump, dill_load, read_json, save_json
from czsc.utils import get_sub_elements, get_py_namespace, freqs_sorted, x_round, import_by_name, create_grid_params
from czsc.utils import cal_trade_price, cross_sectional_ic
from czsc.utils import cal_trade_price, cross_sectional_ic, update_bbars, update_tbars, update_nbars
from czsc.sensors import holds_concepts_effect, StocksDaySensor, ThsConceptsSensor, SignalsPerformance


__version__ = "0.9.16"
__version__ = "0.9.17"
__author__ = "zengbin93"
__email__ = "[email protected]"
__date__ = "20230404"
__date__ = "20230415"


def welcome():
Expand Down
32 changes: 29 additions & 3 deletions czsc/analyze.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,8 @@ def check_bi(bars: List[NewBar], benchmark: float = None):
fxs_ = [x for x in fxs if fx_a.elements[0].dt <= x.dt <= fx_b.elements[2].dt]
bi = BI(symbol=fx_a.symbol, fx_a=fx_a, fx_b=fx_b, fxs=fxs_, direction=direction, bars=bars_a)

low_ubi = min([x.low for x in bars_b])
high_ubi = max([x.high for x in bars_b])
low_ubi = min([x.low for y in bars_b for x in y.raw_bars])
high_ubi = max([x.high for y in bars_b for x in y.raw_bars])
if (bi.direction == Direction.Up and high_ubi > bi.high) \
or (bi.direction == Direction.Down and low_ubi < bi.low):
return None, bars
Expand Down Expand Up @@ -379,6 +379,32 @@ def ubi_fxs(self) -> List[FX]:
else:
return check_fxs(self.bars_ubi)

@property
def ubi(self):
"""Unfinished Bi,未完成的笔"""
if not self.bars_ubi or not self.bi_list:
return None

bars_raw = [y for x in self.bars_ubi for y in x.raw_bars]
# 获取最高点和最低点,以及对应的时间
high_bar = max(bars_raw, key=lambda x: x.high)
low_bar = min(bars_raw, key=lambda x: x.low)
direction = Direction.Up if self.bi_list[-1].direction == Direction.Down else Direction.Down

bi = {
"symbol": self.symbol,
"direction": direction,
"high": high_bar.high,
"low": low_bar.low,
"high_bar": high_bar,
"low_bar": low_bar,
"bars": self.bars_ubi,
"raw_bars": bars_raw,
"fxs": self.ubi_fxs,
"fx_a": self.ubi_fxs[0],
}
return bi

@property
def fx_list(self) -> List[FX]:
"""分型列表,包括 bars_ubi 中的分型"""
Expand All @@ -387,6 +413,6 @@ def fx_list(self) -> List[FX]:
fxs.extend(bi_.fxs[1:])
ubi = self.ubi_fxs
for x in ubi:
if not fxs or x.dt > fxs[-1].dt:
if not fxs or x.dt > fxs[-1].raw_bars[-1].dt:
fxs.append(x)
return fxs
3 changes: 3 additions & 0 deletions czsc/sensors/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,9 @@ def __init__(self, dfs: pd.DataFrame, keys: List[AnyStr]):
:param dfs: 信号表
:param keys: 信号列,支持一个或多个信号列组合分析
"""
base_cols = [x for x in dfs.columns if len(x.split("_")) != 3]
dfs = dfs[base_cols + keys].copy()

if 'year' not in dfs.columns:
y = dfs['dt'].apply(lambda x: x.year)
dfs['year'] = y.values
Expand Down
8 changes: 7 additions & 1 deletion czsc/signals/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
bar_time_V230327,
bar_weekday_V230328,
bar_r_breaker_V230326,
bar_dual_thrust_V230403,
)

from czsc.signals.jcc import (
Expand Down Expand Up @@ -110,6 +111,7 @@
update_kdj_cache,
update_boll_cache,
update_rsi_cache,
update_cci_cache,

tas_macd_base_V221028,
tas_macd_change_V221105,
Expand Down Expand Up @@ -146,6 +148,10 @@
tas_second_bs_V230303,

tas_hlma_V230301,
tas_cci_base_V230402,
tas_kdj_evc_V230401
)


from czsc.signals.pos import (
pos_fx_stop_V230414,
)
59 changes: 59 additions & 0 deletions czsc/signals/bar.py
Original file line number Diff line number Diff line change
Expand Up @@ -939,3 +939,62 @@ def bar_r_breaker_V230326(c: CZSC, **kwargs):
v2 = '其他'

return create_single_signal(k1=k1, k2=k2, k3=k3, v1=v1, v2=v2)


def bar_dual_thrust_V230403(c: CZSC, **kwargs):
"""Dual Thrust 通道突破
参数模板:"{freq}_D{di}通道突破#{N}#{K1}#{K2}_BS辅助V230403"
**信号逻辑:**
参见:https://www.myquant.cn/docs/python_strategyies/424
其核心思想是定义一个区间,区间的上界和下界分别为支撑线和阻力线。当价格超过上界时,看多,跌破下界,看空。
**信号列表:**
- Signal('日线_D1通道突破#5#20#20_BS辅助V230403_看空_任意_任意_0')
- Signal('日线_D1通道突破#5#20#20_BS辅助V230403_看多_任意_任意_0')
:param c: 基础周期的 CZSC 对象
:param kwargs: 其他参数
- di: 倒数第 di 根 K 线
- N: 前N天的数据
- K1: 参数,根据经验优化
- K2: 参数,根据经验优化
:return: 信号字典
"""
di = int(kwargs.get('di', 1))
N = int(kwargs.get('N', 5))
K1 = int(kwargs.get('K1', 20))
K2 = int(kwargs.get('K2', 20))

freq = c.freq.value
k1, k2, k3 = f"{freq}_D{di}通道突破#{N}#{K1}#{K2}_BS辅助V230403".split('_')
if len(c.bars_raw) < 3:
return create_single_signal(k1=k1, k2=k2, k3=k3, v1='其他')

bars = get_sub_elements(c.bars_raw, di=di+1, n=N+1)
HH = max([i.high for i in bars])
HC = max([i.close for i in bars])
LC = min([i.close for i in bars])
LL = min([i.low for i in bars])
Range = max(HH - LC, HC - LL)

current_bar = c.bars_raw[-di]
buy_line = current_bar.open + Range * K1 / 100 # 上轨
sell_line = current_bar.open - Range * K2 / 100 # 下轨

# 根据价格位置判断信号
if current_bar.close > buy_line:
v1 = '看多'
elif current_bar.close < sell_line:
v1 = '看空'
else:
v1 = '其他'

return create_single_signal(k1=k1, k2=k2, k3=k3, v1=v1)



2 changes: 1 addition & 1 deletion czsc/signals/byi.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ def byi_bi_end_V230107(c: CZSC, **kwargs) -> OrderedDict:
return create_single_signal(k1=k1, k2=k2, k3=k3, v1=v1)


def byi_second_bs_V230324(c: CZSC, di=1, **kwargs) -> OrderedDict:
def byi_second_bs_V230324(c: CZSC, **kwargs) -> OrderedDict:
"""白仪二类买卖点辅助V230324
参数模板:"{freq}_D{di}MACD{fastperiod}#{slowperiod}#{signalperiod}回抽零轴_BS2辅助V230324"
Expand Down
67 changes: 67 additions & 0 deletions czsc/signals/pos.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# -*- coding: utf-8 -*-
"""
author: zengbin93
email: [email protected]
create_dt: 2023/4/14 19:27
describe:
"""
from collections import OrderedDict
from czsc.traders.base import CzscTrader
from czsc.utils import create_single_signal
from czsc.objects import Operate, Direction, Mark


def pos_fx_stop_V230414(cat: CzscTrader, **kwargs) -> OrderedDict:
"""按照开仓点附近的分型止损
参数模板:"{freq1}_{pos_name}N{n}_止损V230414"
**信号逻辑:**
多头止损逻辑如下,反之为空头止损逻辑:
1. 从多头开仓点开始,在给定对的K线周期 freq1 上向前找 N 个底分型,记为 F1
2. 将这 N 个底分型的最低点,记为 L1,如果 L1 的价格低于开仓点的价格,则止损
**信号列表:**
- Signal('日线_日线三买多头N1_止损V230414_多头止损_任意_任意_0')
- Signal('日线_日线三买多头N1_止损V230414_空头止损_任意_任意_0')
:param cat: CzscTrader对象
:param kwargs: 参数字典
- pos_name: str,开仓信号的名称
- freq1: str,给定的K线周期
- n: int,向前找的分型个数,默认为 3
:return:
"""
pos_name = kwargs["pos_name"]
freq1 = kwargs["freq1"]
n = int(kwargs.get('n', 3))
k1, k2, k3 = f"{freq1}_{pos_name}N{n}_止损V230414".split("_")
v1 = '其他'

# 如果没有持仓策略,则不产生信号
if not hasattr(cat, "positions"):
return create_single_signal(k1=k1, k2=k2, k3=k3, v1=v1)

pos = [x for x in cat.positions if x.name == pos_name][0]
if len(pos.operates) == 0 or pos.operates[-1]['op'] in [Operate.SE, Operate.LE]:
return create_single_signal(k1=k1, k2=k2, k3=k3, v1=v1)

c = cat.kas[freq1]
op = pos.operates[-1]

# 多头止损逻辑
if op['op'] == Operate.LO:
fxs = [x for x in c.fx_list if x.mark == Mark.D and x.dt < op['dt']][-n:]
if cat.latest_price < min([x.low for x in fxs]):
v1 = '多头止损'

# 空头止损逻辑
if op['op'] == Operate.SO:
fxs = [x for x in c.fx_list if x.mark == Mark.G and x.dt < op['dt']][-n:]
if cat.latest_price > max([x.high for x in fxs]):
v1 = '空头止损'

return create_single_signal(k1=k1, k2=k2, k3=k3, v1=v1)
Loading

0 comments on commit 5024ebb

Please sign in to comment.