Chan-Compass / chan_enhance.py
ranranrunforit's picture
Upload 25 files
16520a2 verified
Raw
History Blame Contribute Delete
4.93 kB
"""
chan_enhance.py —— 缠论系统增强(查漏补缺) · 纯函数版(非Hook)
"""
from __future__ import annotations
W_REVERSAL = 1.0
W_TRAP = 0.85
W_RELAY = 0.6
W_UNKNOWN = 0.7
# 第16课 六种基本走势 → 买法分类的中文名(配合英文 method 一起展示)
METHOD_CN = {
'reversal': '反转式(下跌+盘整+上涨 / 趋势底背驰一买, 力度最强, 权重最高)',
'trap': '陷阱式(下跌+上涨, 空头陷阱式二买, 中等力度)',
'relay': '中继式(上涨+盘整+上涨, 三买, 趋势中继)',
'unknown': '未分类',
}
WEAK_ARM_GAIN = 0.04
WEAK_GIVEBACK = 0.22
L92_EXIT_ENABLE = False
L92_EXIT_FLOATING_MAX = 0.015
L92_ZD_BREAK_BUF = 0.0
def classify_buy_method(sig_kind, ml) -> str:
sig = ml.daily.signal if (ml and ml.daily) else None
dg = getattr(sig, 'diverge_grade', None) if sig is not None else None
if sig_kind == 'B1':
return 'reversal'
if sig_kind == 'B3':
return 'relay'
if sig_kind == 'B2':
# L37 背驰分辨: 只有"趋势背驰"(≥2个同向中枢后的背驰)才是标准的趋势转折,
# 对应第16课"下跌+盘整+上涨"反转式买法; 盘整背驰力度弱, 仍按陷阱式处理。
if (dg is not None and getattr(dg, 'grade', '') == 'STRONG'
and getattr(dg, 'is_trend_divergence', False)):
return 'reversal'
return 'trap'
return 'unknown'
def l37_divergence_note(ml) -> str:
"""L37 背驰分辨(区分背驰段构成): 趋势背驰=至少两个同向中枢后的背驰, 转折级别高;
盘整背驰=单中枢内的力度衰竭, 只保证回拉中枢, 不保证反转。"""
sig = ml.daily.signal if (ml and ml.daily) else None
dg = getattr(sig, 'diverge_grade', None) if sig is not None else None
if dg is None or getattr(dg, 'grade', 'NONE') == 'NONE':
return ''
if getattr(dg, 'is_trend_divergence', False):
return (f'第37课: 趋势背驰({getattr(dg, "n_trend_pivots", "?")}个同向中枢), '
f'转折至少回拉至最后一个中枢, 大概率反转 → 可按反转式买法重仓')
return ('第37课: 盘整背驰(背驰段内仅1个中枢), 只保证回拉中枢一次, '
'不保证趋势反转 → 轻仓短打, 回拉到中枢即考虑兑现')
def buy_method_weight(sig_kind, ml):
method = classify_buy_method(sig_kind, ml)
wmap = {'reversal': W_REVERSAL, 'trap': W_TRAP, 'relay': W_RELAY, 'unknown': W_UNKNOWN}
return method, wmap.get(method, W_UNKNOWN)
def recompute_evo(ml) -> str:
sig = ml.daily.signal if (ml and ml.daily) else None
if sig is not None:
evo = (sig.extras or {}).get('post_evolution', '')
if evo:
return evo
dv = ml.daily if ml else None
if dv is not None and dv.zd is not None and dv.zg is not None:
if ml.cur_price < dv.zd:
return 'case1_extend'
return ''
def weak_evo_giveback(pos, ml, default_giveback):
evo = recompute_evo(ml) if ml is not None else (pos.get('post_evo') or '')
if evo == 'case1_extend':
return WEAK_ARM_GAIN, WEAK_GIVEBACK
return None, default_giveback
def l92_should_exit(pos, ml, close_p, floating):
if not L92_EXIT_ENABLE or ml is None or ml.daily is None:
return None
if floating > L92_EXIT_FLOATING_MAX:
return None
zd = ml.daily.zd
if zd is None:
return None
if close_p < zd * (1 - L92_ZD_BREAK_BUF) and close_p > pos.get('stop_px', 0):
return ('L92_EXIT',
f'第92课中枢震荡监视器: 现价{close_p:.3f}已破日线中枢下沿ZD{zd:.3f}'
f'(向下变盘) 且浮盈仅{floating:+.1%} → 提前减仓, 不等磨到结构止损')
return None
def predict_enhance(ml) -> dict:
out = {}
if ml is None or ml.daily is None:
return out
sig_kind = ml.final_kind or ''
if sig_kind in ('B1', 'B2', 'B3'):
method, weight = buy_method_weight(sig_kind, ml)
out['buy_method'] = method
out['buy_method_cn'] = METHOD_CN.get(method, method)
out['suggest_weight'] = weight
out['l16_note'] = f'第16课: 买法分类={method}{METHOD_CN.get(method, method)}〕, 建议仓位权重{weight:.2f}'
l37 = l37_divergence_note(ml)
if l37:
out['l37_note'] = l37
evo = recompute_evo(ml)
if evo:
out['post_evolution'] = evo
out['evo_hint'] = ('第29课: 最弱形态(反弹/回落未回中枢), 持有宜收紧移动止盈, 尽快兑现'
if evo == 'case1_extend'
else '第29课: 形态较强(回到中枢), 可持有等三买/趋势延续')
zd = ml.daily.zd
if zd is not None and ml.cur_price < zd:
out['l92_warn'] = f'第92课: 现价{ml.cur_price:.3f}已在日线中枢下沿ZD{zd:.3f}下方 → 向下变盘预警'
return out