Skip to content

Commit

Permalink
V0.9.15 更新一批代码 (waditu#138)
Browse files Browse the repository at this point in the history
* 0.9.15 start coding

* 0.9.15 fix bug

* 0.9.15 fix bug

* 0.9.15 彻底删除 get_signals 参数

* 0.9.15 新增投研数据共享接口

* 0.9.15 update

* 0.9.15 update

* 0.9.15 update

* 0.9.15 update

* 0.9.15 update

* 0.9.15 update

* 0.9.15 update

* 0.9.15 update

* 0.9.15 update docs

* 0.9.15 新增 config_to_keys

* 0.9.15 update

* 0.9.15 优化 get_signals_freqs 方法

* 0.9.15 update

* 0.9.15 update

* 0.9.15 fix bug: dummy 模式下 sdt 不生效
  • Loading branch information
zengbin93 authored Apr 3, 2023
1 parent 1bc2422 commit 1f59136
Show file tree
Hide file tree
Showing 35 changed files with 315 additions and 1,344 deletions.
2 changes: 1 addition & 1 deletion .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.14 ]
branches: [ master, V0.9.15 ]
pull_request:
branches: [ master ]

Expand Down
4 changes: 2 additions & 2 deletions czsc/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@
from czsc.sensors import holds_concepts_effect, StocksDaySensor, ThsConceptsSensor, SignalsPerformance


__version__ = "0.9.14"
__version__ = "0.9.15"
__author__ = "zengbin93"
__email__ = "[email protected]"
__date__ = "20230323"
__date__ = "20230331"


def welcome():
Expand Down
16 changes: 10 additions & 6 deletions czsc/connectors/gm_connector.py
Original file line number Diff line number Diff line change
Expand Up @@ -598,7 +598,7 @@ def sync_long_position(context, trader: CzscTrader):

symbol = trader.symbol
name = context.stocks.get(symbol, "无名标的")
long_pos = trader.get_ensemble_pos(method='vote')
ensemble_pos = trader.get_ensemble_pos(method='vote')
max_sym_pos = context.symbols_info[symbol]['max_sym_pos'] # 最大标的仓位
if context.mode == MODE_BACKTEST:
account = context.account()
Expand All @@ -608,20 +608,24 @@ def sync_long_position(context, trader: CzscTrader):

price = trader.latest_price
sym_position = account.position(symbol, PositionSide_Long)
if long_pos == 0 and not sym_position:
if ensemble_pos == 0 and not sym_position:
# 如果多头仓位为0且掘金账户没有对应持仓,直接退出
return

if long_pos == 0 and sym_position and sym_position.volume > 0:
if ensemble_pos == 0 and sym_position and sym_position.volume > 0:
# 如果多头仓位为0且掘金账户依然还有持仓,清掉仓位
order_target_volume(symbol=symbol, volume=0, position_side=PositionSide_Long,
order_type=OrderType_Limit, price=price, account=account.id)
return

# 没有仓位变化,直接退出
if not trader.pos_changed:
return

assert long_pos > 0
# 仓位指向空头,直接退出
if ensemble_pos < 0:
return

if cash.available < price * 120:
logger.info(f"{context.now} {symbol} {name} 可用资金不足,无法开多仓,最少所需资金{int(price * 120)}元")
return
Expand All @@ -630,7 +634,7 @@ def sync_long_position(context, trader: CzscTrader):
logger.info(f"{context.now} {symbol} {name} 同方向订单已存在")
return

percent = max_sym_pos * long_pos
percent = max_sym_pos * ensemble_pos
volume = int((cash.nav * percent / price // 100) * 100) # 单位:股
order_target_volume(symbol=symbol, volume=volume, position_side=PositionSide_Long,
order_type=OrderType_Limit, price=price, account=account.id)
Expand Down Expand Up @@ -736,7 +740,7 @@ def init_context_traders(context, symbols: List[str], strategy):
else:
tactic = strategy(symbol=symbol)
bg, data = get_init_bg(symbol, context.now, base_freq, freqs, 1000, ADJUST_PREV)
trader = CzscTrader(bg, get_signals=tactic.get_signals, positions=tactic.positions)
trader = CzscTrader(bg, signals_config=tactic.signals_config, positions=tactic.positions)
dill.dump(trader, open(file_trader, 'wb'))

symbols_info[symbol]['trader'] = trader
Expand Down
55 changes: 55 additions & 0 deletions czsc/connectors/research.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# -*- coding: utf-8 -*-
"""
author: zengbin93
email: [email protected]
create_dt: 2023/3/5 20:45
describe: CZSC投研数据共享接口
投研数据共享说明(含下载地址):https://s0cqcxuy3p.feishu.cn/wiki/wikcnzuPawXtBB7Cj7mqlYZxpDh
"""
import os
import czsc
import glob
import pandas as pd

# 投研共享数据的本地缓存路径,需要根据实际情况修改
cache_path = os.environ.get('czsc_research_cache', r"D:\CZSC投研数据")
if not os.path.exists(cache_path):
raise ValueError(f"请设置环境变量 czsc_research_cache 为投研共享数据的本地缓存路径,当前路径不存在:{cache_path}\n\n"
f"投研数据共享说明(含下载地址):https://s0cqcxuy3p.feishu.cn/wiki/wikcnzuPawXtBB7Cj7mqlYZxpDh")


def get_symbols(name, **kwargs):
"""获取指定分组下的所有标的代码
:param name: 分组名称,可选值:'A股主要指数', 'A股场内基金', '中证500成分股', '期货主力'
:param kwargs:
:return:
"""
files = glob.glob(os.path.join(cache_path, name, "*.parquet"))
return [os.path.basename(x).replace('.parquet', '') for x in files]


def get_raw_bars(symbol, freq, sdt, edt, fq='前复权', **kwargs):
"""获取 CZSC 库定义的标准 RawBar 对象列表
:param symbol: 标的代码
:param freq: 周期,支持 Freq 对象,或者字符串,如
'1分钟', '5分钟', '15分钟', '30分钟', '60分钟', '日线', '周线', '月线', '季线', '年线'
:param sdt: 开始时间
:param edt: 结束时间
:param fq: 除权类型,投研共享数据默认都是后复权,不需要再处理
:param kwargs:
:return:
"""
kwargs['fq'] = fq
file = glob.glob(os.path.join(cache_path, "*", f"{symbol}.parquet"))[0]
freq = czsc.Freq(freq)
kline = pd.read_parquet(file)
if 'dt' not in kline.columns:
kline['dt'] = pd.to_datetime(kline['datetime'])
kline = kline[(kline['dt'] >= sdt) & (kline['dt'] <= edt)]
_bars = czsc.resample_bars(kline, freq, raw_bars=True)
return _bars


9 changes: 6 additions & 3 deletions czsc/signals/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,7 @@
from czsc.signals.bar import (
bar_end_V221111,
bar_operate_span_V221111,
bar_zdt_V221110,
bar_zdt_V221111,
bar_zdt_V230313,
bar_zdt_V230331,
bar_cross_ps_V221112,
bar_section_momentum_V221112,
bar_vol_grow_V221112,
Expand All @@ -80,6 +78,11 @@
bar_time_V230327,
bar_weekday_V230328,
bar_r_breaker_V230326,

# 以下是旧版本的信号函数,不再维护,仅供参考,不要使用
bar_zdt_V221110,
bar_zdt_V221111,
bar_zdt_V230313,
)

from czsc.signals.jcc import (
Expand Down
39 changes: 39 additions & 0 deletions czsc/signals/bar.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from datetime import datetime
from typing import List
from loguru import logger
from deprecated import deprecated
from collections import OrderedDict
from czsc import envs, CZSC, Signal
from czsc.traders.base import CzscSignals
Expand Down Expand Up @@ -60,6 +61,42 @@ def bar_operate_span_V221111(c: CZSC, k1: str = '开多', span=("1400", "1450"))
return create_single_signal(k1=k1, k2=k2, k3=k3, v1=v)


def bar_zdt_V230331(c: CZSC, **kwargs) -> OrderedDict:
"""计算倒数第di根K线的涨跌停信息
参数模板:"{freq}_D{di}_涨跌停V230331"
**信号逻辑:**
- close等于high大于等于前一根K线的close,近似认为是涨停;反之,跌停。
**信号列表:**
- Signal('15分钟_D1_涨跌停V230331_涨停_任意_任意_0')
- Signal('15分钟_D1_涨跌停V230331_跌停_任意_任意_0')
:param c: 基础周期的 CZSC 对象
:param kwargs:
- di: 倒数第 di 根 K 线
:return: 信号识别结果
"""
di = int(kwargs.get("di", 1))
freq = c.freq.value
k1, k2, k3 = f"{freq}_D{di}_涨跌停V230331".split("_")
v1 = "其他"
if len(c.bars_raw) < di + 2:
return create_single_signal(k1=k1, k2=k2, k3=k3, v1=v1)

b1, b2 = c.bars_raw[-di], c.bars_raw[-di - 1]
if b1.close == b1.high >= b2.close:
v1 = "涨停"
elif b1.close == b1.low <= b2.close:
v1 = "跌停"

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


@deprecated(version="0.9.16", reason="这个信号函数不符合规范;请使用 bar_zdt_V230331")
def bar_zdt_V221110(c: CZSC, di=1) -> OrderedDict:
"""计算倒数第di根K线的涨跌停信息
Expand Down Expand Up @@ -95,6 +132,7 @@ def bar_zdt_V221110(c: CZSC, di=1) -> OrderedDict:
return create_single_signal(k1=k1, k2=k2, k3=k3, v1=v1)


@deprecated(version="0.9.16", reason="这个信号函数不符合规范;请使用 bar_zdt_V230331")
def bar_zdt_V230313(c: CZSC, di=1, **kwargs) -> OrderedDict:
"""计算倒数第di根K线的涨跌停信息
Expand Down Expand Up @@ -124,6 +162,7 @@ def bar_zdt_V230313(c: CZSC, di=1, **kwargs) -> OrderedDict:
return create_single_signal(k1=k1, k2=k2, k3=k3, v1=v1)


@deprecated(version="0.9.16", reason="这个信号函数不符合规范;请使用 bar_zdt_V230331")
def bar_zdt_V221111(cat: CzscSignals, freq: str, di: int = 1) -> OrderedDict:
"""更精确地倒数第1根K线的涨跌停计算
Expand Down
19 changes: 10 additions & 9 deletions czsc/signals/tas.py
Original file line number Diff line number Diff line change
Expand Up @@ -698,7 +698,7 @@ def tas_ma_base_V221101(c: CZSC, **kwargs) -> OrderedDict:
return create_single_signal(k1=k1, k2=k2, k3=k3, v1=v1, v2=v2)


def tas_ma_base_V221203(c: CZSC, di: int = 1, ma_type='SMA', timeperiod=5, th=100, **kwargs) -> OrderedDict:
def tas_ma_base_V221203(c: CZSC, **kwargs) -> OrderedDict:
"""MA 多空和方向信号,加距离限制
参数模板:"{freq}_D{di}{ma_type}#{timeperiod}T{th}_分类V221203"
Expand All @@ -721,11 +721,12 @@ def tas_ma_base_V221203(c: CZSC, di: int = 1, ma_type='SMA', timeperiod=5, th=10
- Signal('15分钟_D1SMA#5T100_分类V221203_空头_向上_远离_0')
:param c: CZSC对象
:param di: 信号计算截止倒数第i根K线
:param ma_type: 均线类型,必须是 `ma_type_map` 中的 key
:param timeperiod: 均线计算周期
:param th: 距离阈值,单位 BP
:return:
:param kwargs:
- di: 信号计算截止倒数第i根K线
- ma_type: 均线类型,必须是 `ma_type_map` 中的 key
- timeperiod: 均线计算周期
- th: 距离阈值,单位 BP
:return: 信号识别结果
"""
di = int(kwargs.get('di', 1))
ma_type = kwargs.get('ma_type', 'SMA').upper()
Expand Down Expand Up @@ -979,9 +980,9 @@ def update_kdj_cache(c: CZSC, **kwargs):
:param c: CZSC对象
:return:
"""
fastk_period = kwargs.get('fastk_period', 9)
slowk_period = kwargs.get('slowk_period', 3)
slowd_period = kwargs.get('slowd_period', 3)
fastk_period = int(kwargs.get('fastk_period', 9))
slowk_period = int(kwargs.get('slowk_period', 3))
slowd_period = int(kwargs.get('slowd_period', 3))
cache_key = f"KDJ{fastk_period}#{slowk_period}#{slowd_period}"

if c.bars_raw[-1].cache and c.bars_raw[-1].cache.get(cache_key, None):
Expand Down
Loading

0 comments on commit 1f59136

Please sign in to comment.