docs: 补充回测结果摘要 + 策略文档 + Dashboard 后端 + 整理目录结构
This commit is contained in:
531
docs/v1.6_strategy_doc.md
Normal file
531
docs/v1.6_strategy_doc.md
Normal file
@ -0,0 +1,531 @@
|
||||
# StructureFlowStrategy v1.6 — 完整策略解析文档
|
||||
|
||||
> 写给自己看的版本,在下一次优化开始前彻底搞清楚这 436 行代码在做什么。
|
||||
|
||||
---
|
||||
|
||||
## 一、策略大纲
|
||||
|
||||
这是一个**纯价格行为策略**,零指标(没有 MACD、RSI、布林带……),只用 K 线结构做决策。
|
||||
|
||||
核心思想只有一句话:
|
||||
|
||||
> **在大趋势方向上,找到有效的支撑/阻力位,等价格出现反转形态信号时入场,让市场结构自动追踪止损。**
|
||||
|
||||
三层时间框架,各司其职:
|
||||
|
||||
```
|
||||
D1(日线) → 判断方向:现在是涨势还是跌势?
|
||||
4H(四小时)→ 找位置:支撑/阻力在哪里?价格在需求区还是供给区?
|
||||
1H(一小时)→ 找时机:此时此刻有没有反转信号?
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 二、整体代码结构图
|
||||
|
||||
```
|
||||
StructureFlowStrategyV16
|
||||
│
|
||||
├── 工具函数(静态方法)
|
||||
│ ├── _detect_swing_points() ← 找 Swing High / Swing Low
|
||||
│ ├── _build_structure() ← 分析结构:趋势、支撑、阻力、供需区
|
||||
│ └── _detect_candle_patterns() ← 识别 K 线形态:Pin Bar、吞没
|
||||
│
|
||||
├── 指标计算(按时间框架)
|
||||
│ ├── populate_indicators_1d() ← D1:计算日线趋势方向
|
||||
│ ├── populate_indicators_4h() ← 4H:计算中期结构 + 活支撑/阻力(v1.6新增)
|
||||
│ └── populate_indicators() ← 1H:识别 K 线形态
|
||||
│
|
||||
├── 信号逻辑
|
||||
│ ├── populate_entry_trend() ← 入场条件(6个条件全满足才进)
|
||||
│ └── populate_exit_trend() ← 出场条件(D1 趋势反转时退出)
|
||||
│
|
||||
└── 动态止损
|
||||
└── custom_stoploss() ← 基于 4H Swing Point 的结构止损
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 三、基础参数说明
|
||||
|
||||
```python
|
||||
can_short = True # 允许做空(合约模式)
|
||||
stoploss = -0.15 # 兜底止损:最大允许亏损 15%(custom_stoploss 的安全边界)
|
||||
use_custom_stoploss = True # 启用自定义止损逻辑
|
||||
minimal_roi = {"0": 100} # 关闭固定止盈(100 = 永不触发)
|
||||
max_open_trades = 1 # 同时最多 1 笔交易(专注单品种)
|
||||
timeframe = "1h" # 主时间框架:1小时
|
||||
```
|
||||
|
||||
**关于 `stoploss = -0.15` 和 `custom_stoploss` 的关系:**
|
||||
|
||||
- `custom_stoploss` 是每根 K 线都会调用的动态止损逻辑
|
||||
- `-0.15` 是**硬边界**:即使 `custom_stoploss` 返回了一个更宽的止损,freqtrade 也会把它截断到 -15%
|
||||
- 这两个是"主控 + 保险"的关系,不是矛盾的
|
||||
|
||||
---
|
||||
|
||||
## 四、可优化参数
|
||||
|
||||
```python
|
||||
swing_lookback_d1 = IntParameter(8, 14, default=10, space="buy")
|
||||
# D1 识别 Swing Point 的回溯窗口:10 意味着一个高点必须是
|
||||
# 左侧 10 根日线和右侧 10 根日线里的最高点,才算 Swing High。
|
||||
# 数字越大 → Swing Point 越稀疏越重要
|
||||
# 数字越小 → Swing Point 越密集越灵敏
|
||||
|
||||
swing_lookback_h4 = IntParameter(5, 10, default=8, space="buy")
|
||||
# 4H 级别的 Swing Point 回溯窗口,逻辑同上
|
||||
|
||||
pin_bar_wick_ratio = IntParameter(50, 70, default=60, space="buy")
|
||||
# Pin Bar 识别阈值:影线占整根 K 线的比例
|
||||
# 60 表示 "影线占比 > 60% 才算 Pin Bar"
|
||||
# 数字越大 → 只认最标准的 Pin Bar(更严格)
|
||||
# 数字越小 → 稍微有点影线就算(更宽松)
|
||||
|
||||
max_stop_dist = IntParameter(20, 50, default=50, space="buy")
|
||||
# 止损距离上限:入场价到支撑位的距离不能超过 50%
|
||||
# 防止"支撑位太远、止损太大"的情况
|
||||
# 实际上 default=50 几乎不过滤(等于没有限制)
|
||||
|
||||
cooldown_bars = IntParameter(3, 12, default=6, space="buy")
|
||||
# v1.6 新增:冷却期(单位:1H K 线根数)
|
||||
# 6 表示:上一个同方向信号出现后,6 小时内不再产生新信号
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 五、工具函数详解
|
||||
|
||||
### 5.1 `_detect_swing_points()` — 找摆动高低点
|
||||
|
||||
```python
|
||||
for i in range(window, n - window):
|
||||
# 条件:第 i 根的 high > 左边 window 根的最高 AND > 右边 window 根的最高
|
||||
if high[i] > high[i-window:i].max() and high[i] > high[i+1:i+window+1].max():
|
||||
sh[i] = high[i] # 这是一个 Swing High
|
||||
# 对称的逻辑找 Swing Low
|
||||
if low[i] < low[i-window:i].min() and low[i] < low[i+1:i+window+1].min():
|
||||
sl[i] = low[i] # 这是一个 Swing Low
|
||||
```
|
||||
|
||||
**视觉理解:**
|
||||
|
||||
```
|
||||
▲ Swing High(左右各 window 根都是低点)
|
||||
/|\
|
||||
/ | \
|
||||
───────────────/ | \───────────
|
||||
```
|
||||
|
||||
**重要细节:** `range(window, n - window)` 意味着最后 `window` 根 K 线无法被识别为 Swing Point(因为需要看右边的数据)。这在实盘中意味着**最近的高低点要滞后 window 根才被确认**。
|
||||
|
||||
---
|
||||
|
||||
### 5.2 `_build_structure()` — 分析市场结构
|
||||
|
||||
这个函数是整个策略的大脑,逐根 K 线地维护 5 个状态:
|
||||
|
||||
#### (1)趋势判断
|
||||
|
||||
```python
|
||||
# 记录最近 4 个 Swing High 和 4 个 Swing Low
|
||||
sh_prices = [] # 最多保留 4 个
|
||||
sl_prices = []
|
||||
|
||||
# 趋势判断逻辑(HH/HL vs LH/LL)
|
||||
if sh_prices[-1] > sh_prices[-2] and sl_prices[-1] > sl_prices[-2]:
|
||||
trend_up = True # HH (Higher High) + HL (Higher Low) = 上升趋势
|
||||
elif sh_prices[-1] < sh_prices[-2] and sl_prices[-1] < sl_prices[-2]:
|
||||
trend_down = True # LH (Lower High) + LL (Lower Low) = 下降趋势
|
||||
else:
|
||||
# 结构不明确时,继承上一根的趋势(趋势具有惯性)
|
||||
trend_up[i] = trend_up[i-1]
|
||||
trend_down[i] = trend_down[i-1]
|
||||
```
|
||||
|
||||
**这就是价格行为学的核心:**
|
||||
- 上升趋势 = Higher High + Higher Low(HH + HL)
|
||||
- 下降趋势 = Lower High + Lower Low(LH + LL)
|
||||
|
||||
#### (2)最近支撑/阻力
|
||||
|
||||
```python
|
||||
nearest_support[i] = sl_prices[-1] # 最近的 Swing Low = 支撑
|
||||
nearest_resistance[i] = sh_prices[-1] # 最近的 Swing High = 阻力
|
||||
```
|
||||
|
||||
**注意:** 这里直接取最后一个 Swing Low 作为支撑,没有考虑位置关系(支撑可能在当前价格之上)。这是一个潜在的逻辑弱点,后续优化可以考虑。
|
||||
|
||||
#### (3)供需区划分
|
||||
|
||||
```python
|
||||
zone_range = resistance - support
|
||||
pos_pct = (close - support) / zone_range
|
||||
|
||||
in_demand_zone = pos_pct < 0.35 # 价格在 support↔resistance 区间的底部 35%
|
||||
in_supply_zone = pos_pct > 0.65 # 价格在 support↔resistance 区间的顶部 35%
|
||||
```
|
||||
|
||||
**视觉理解:**
|
||||
|
||||
```
|
||||
┌─────────────────────────────────┐
|
||||
│ resistance ────────────────── │
|
||||
│ 供给区(Supply Zone, >65%) │ ← 做空区域
|
||||
│ ─────────────────────────── 65%│
|
||||
│ │
|
||||
│ 中间区(35%~65%) │ ← 不入场
|
||||
│ │
|
||||
│ ─────────────────────────── 35%│
|
||||
│ 需求区(Demand Zone, <35%) │ ← 做多区域
|
||||
│ support ──────────────────── │
|
||||
└─────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 5.3 `_detect_candle_patterns()` — K 线形态识别
|
||||
|
||||
#### Pin Bar(Pin 柱/别针 K 线)
|
||||
|
||||
```python
|
||||
body = abs(close - open_) # 实体大小
|
||||
total_range = high - low # 整根 K 线的范围
|
||||
upper_wick = high - max(close, open_) # 上影线长度
|
||||
lower_wick = min(close, open_) - low # 下影线长度
|
||||
|
||||
is_pin = (upper_wick + lower_wick) / total_range > pin_bar_wick_ratio
|
||||
# 当影线占比 > 60%,才算 Pin Bar
|
||||
|
||||
# 看涨 Pin Bar:阳线 + 下影线 > 上影线(价格被撑住了)
|
||||
bullish_pin = is_pin & (close > open_) & (lower_wick > upper_wick)
|
||||
|
||||
# 看跌 Pin Bar:阴线 + 上影线 > 下影线(价格被压下来了)
|
||||
bearish_pin = is_pin & (close < open_) & (upper_wick > lower_wick)
|
||||
```
|
||||
|
||||
**视觉理解:**
|
||||
|
||||
```
|
||||
看涨 Pin Bar 看跌 Pin Bar
|
||||
│ ██████
|
||||
│ │
|
||||
███ │
|
||||
│ │
|
||||
███████ ███████
|
||||
│
|
||||
███████
|
||||
```
|
||||
|
||||
#### 吞没形态(Engulfing)
|
||||
|
||||
```python
|
||||
# 看涨吞没:阳线,收盘 > 前根开盘,开盘 < 前根收盘
|
||||
bullish_engulf = (close > prev_open) & (open_ < prev_close) & (close > open_)
|
||||
|
||||
# 看跌吞没:阴线,收盘 < 前根开盘,开盘 > 前根收盘
|
||||
bearish_engulf = (close < prev_open) & (open_ > prev_close) & (close < open_)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 六、时间框架指标详解
|
||||
|
||||
### 6.1 D1 日线(`populate_indicators_1d`)
|
||||
|
||||
**只做一件事:确定宏观趋势方向**
|
||||
|
||||
- `trend_up_1d = True` → 日线是上升趋势(HH + HL)
|
||||
- `trend_down_1d = True` → 日线是下降趋势(LH + LL)
|
||||
|
||||
回溯窗口 `swing_lookback_d1 = 10`,意味着确认一个日线 Swing Point 需要左右各 10 天,合计 20 天。这是有意为之——**日线趋势应该稳定,不应该频繁切换**。
|
||||
|
||||
---
|
||||
|
||||
### 6.2 4H 四小时(`populate_indicators_4h`)
|
||||
|
||||
**做五件事:**
|
||||
|
||||
1. `trend_up_4h` / `trend_down_4h`:4H 中期趋势(与 D1 配合,双重确认)
|
||||
2. `support_4h`:最近的 4H Swing Low(止损基准点)
|
||||
3. `resistance_4h`:最近的 4H Swing High(做空止损基准点)
|
||||
4. `in_demand_4h`:当前 1H 价格是否在 4H 需求区(做多区域)
|
||||
5. `in_supply_4h`:当前 1H 价格是否在 4H 供给区(做空区域)
|
||||
|
||||
**v1.6 新增:活支撑/阻力判断**
|
||||
|
||||
```python
|
||||
# 支撑"活"的判断:
|
||||
# 条件1:最近某根 4H K 线的 low,触及 support ± 0.5% 的范围
|
||||
touched_support = (low <= support * 1.005) & (low >= support * 0.995)
|
||||
|
||||
# 条件2:那根 K 线的收盘价在 support 之上(撑住了,没跌穿)
|
||||
held_support = close > support
|
||||
|
||||
# 两个条件都满足,才算"一次有效测试"
|
||||
support_tested_and_held = touched_support & held_support
|
||||
|
||||
# 在最近 3 根 4H K 线内,至少发生过一次有效测试 → 支撑是"活"的
|
||||
dataframe["support_alive"] = support_tested_and_held.rolling(3, min_periods=1).max() > 0
|
||||
```
|
||||
|
||||
**为什么要"活支撑"?**
|
||||
|
||||
"死支撑"是指那些很久以前的 Swing Low,现在价格距离它很远,支撑位已经失效。例如:
|
||||
|
||||
```
|
||||
3个月前的 Swing Low = 1500 美元(支撑)
|
||||
但价格从那之后一直在 2000-2500 之间波动,从未回测过 1500
|
||||
→ 1500 的支撑已经是"死"的,在那里做多没有意义
|
||||
```
|
||||
|
||||
v1.6 要求:支撑必须是**最近 3 根 4H K 线内有价格来测试过的**,才算有效。
|
||||
|
||||
**"活支撑" 的问题(客观评价):**
|
||||
- `rolling(3)` = 最近 12 小时(3 × 4H)内测试过
|
||||
- 这个窗口是否合适?12 小时可能太短,也可能太长
|
||||
- 是未来优化的方向之一
|
||||
|
||||
---
|
||||
|
||||
### 6.3 1H 一小时(`populate_indicators`)
|
||||
|
||||
**只做一件事:识别 K 线反转形态**
|
||||
|
||||
```python
|
||||
dataframe["bullish_signal"] = bullish_pin | bullish_engulf # 两种看涨形态满足任一
|
||||
dataframe["bearish_signal"] = bearish_pin | bearish_engulf # 两种看跌形态满足任一
|
||||
```
|
||||
|
||||
**NaN 安全处理:**
|
||||
由于不同时间框架的数据合并(D1、4H → 1H)会产生空值,这里统一对布尔列做 `fillna(False)`,防止 `True & NaN = NaN` 导致信号丢失。
|
||||
|
||||
---
|
||||
|
||||
## 七、入场逻辑详解
|
||||
|
||||
### 做多条件(6 个条件全部满足)
|
||||
|
||||
```python
|
||||
long_base = (
|
||||
dataframe["trend_up_1d"] # 条件1:日线是上升趋势
|
||||
& dataframe["in_demand_4h"] # 条件2:当前价格在 4H 需求区(支撑附近)
|
||||
& dataframe["bullish_signal"] # 条件3:1H 出现看涨 K 线形态
|
||||
& (long_stop_dist <= max_dist) # 条件4:止损距离 ≤ 50%(几乎不过滤)
|
||||
& (long_stop_dist > 0.003) # 条件5:止损距离 > 0.3%(防止支撑=开盘价)
|
||||
)
|
||||
|
||||
long_base = long_base & dataframe["support_alive_4h"] # 条件6:支撑是"活"的 [v1.6]
|
||||
|
||||
long_recent = long_base.rolling(cooldown).max().shift(1) == 0 # 冷却期过滤 [v1.6]
|
||||
long_conditions = long_base & long_recent
|
||||
```
|
||||
|
||||
**条件5 的意义:** `long_stop_dist > 0.003` 防止"支撑位和开盘价几乎相同"的情况,那样止损太近,任何正常波动都会触发。
|
||||
|
||||
### 冷却期的工作原理
|
||||
|
||||
```python
|
||||
# long_base 是"条件1-6都满足"的信号(不含冷却)
|
||||
# rolling(6).max() → 过去6根1H bar内,是否有过满足条件的信号(1=有,0=没有)
|
||||
# .shift(1) → 往后移一格,避免当前这根K线跟自己比较
|
||||
# == 0 → 只有"过去6小时内没有信号"时,才允许当前入场
|
||||
|
||||
long_recent = long_base.rolling(cooldown, min_periods=1).max().shift(1) == 0
|
||||
```
|
||||
|
||||
**视觉理解(cooldown=6):**
|
||||
|
||||
```
|
||||
时间 → 1h 2h 3h 4h 5h 6h 7h 8h 9h 10h
|
||||
信号 ✓ ✓
|
||||
冷却期 ←── 6小时冷却 ──→
|
||||
允许入场 ✓ ✓ (第10小时重新可以入场)
|
||||
```
|
||||
|
||||
### 做空条件(对称)
|
||||
|
||||
```python
|
||||
short_base = (
|
||||
dataframe["trend_down_1d"] # 条件1:日线是下降趋势
|
||||
& dataframe["in_supply_4h"] # 条件2:价格在 4H 供给区(阻力附近)
|
||||
& dataframe["bearish_signal"] # 条件3:1H 出现看跌 K 线形态
|
||||
& (short_stop_dist <= max_dist) # 条件4:止损距离合理
|
||||
& (short_stop_dist > 0.003) # 条件5:止损距离不为零
|
||||
)
|
||||
short_base = short_base & dataframe["resistance_alive_4h"] # 条件6:阻力是"活"的
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 八、出场逻辑详解
|
||||
|
||||
```python
|
||||
exit_long = ~dataframe["trend_up_1d"].fillna(True) # 当 D1 趋势不再上升时平多
|
||||
exit_short = dataframe["trend_up_1d"].fillna(False) # 当 D1 趋势转为上升时平空
|
||||
```
|
||||
|
||||
**这个逻辑非常简单,也非常粗糙:**
|
||||
|
||||
- 只有 D1 趋势反转时才触发出场信号
|
||||
- D1 趋势需要明确的 HH+HL 或 LH+LL 才会切换,这需要较长时间
|
||||
- 结果:大多数交易不会触发 exit_signal,而是由止损(stop_loss 或 trailing_stop_loss)退出
|
||||
|
||||
这也是为什么回测中 `exit_signal` 只有 7-9 笔,而止损退出有 70-100 笔。
|
||||
|
||||
---
|
||||
|
||||
## 九、动态止损详解(最核心的部分)
|
||||
|
||||
```python
|
||||
def custom_stoploss(self, pair, trade, current_time, current_rate, current_profit, ...):
|
||||
last = dataframe.iloc[-1] # 取最新的 4H 数据
|
||||
|
||||
if not trade.is_short: # 多单
|
||||
support = last["support_4h"] # 最近的 4H Swing Low
|
||||
sl_price = support * 0.999 # 止损价 = 支撑位下方 0.1%
|
||||
sl_ratio = (sl_price / current_rate) - 1.0 # 转换为相对于当前价格的比率
|
||||
return max(sl_ratio, -0.15) # 不超过 -15% 的硬边界
|
||||
else: # 空单
|
||||
resistance = last["resistance_4h"] # 最近的 4H Swing High
|
||||
sl_price = resistance * 1.001 # 止损价 = 阻力位上方 0.1%
|
||||
sl_ratio = 1.0 - (sl_price / current_rate)
|
||||
return min(sl_ratio, 0.15) # 不超过 +15% 的硬边界
|
||||
```
|
||||
|
||||
### 为什么这会产生"自然追踪止损效果"?
|
||||
|
||||
关键在于 `support_4h` 是**动态更新**的:
|
||||
|
||||
```
|
||||
t=0 入场,support_4h = 1800(止损在 1798.2)
|
||||
价格从 1850 开始上涨
|
||||
t=5h 价格涨到 2000,出现新 Swing Low = 1900
|
||||
→ support_4h 更新为 1900
|
||||
→ 止损自动上移到 1898.1
|
||||
t=10h 价格涨到 2200,新 Swing Low = 2050
|
||||
→ support_4h 更新为 2050
|
||||
→ 止损上移到 2047.9
|
||||
```
|
||||
|
||||
这就是为什么 `trailing_stop_loss` 出现那么多:每当价格创新高、产生新的 Swing Low,止损就自动追上去,锁住利润。
|
||||
|
||||
### 止损的数学计算示例
|
||||
|
||||
假设:
|
||||
- 当前价格 = 2000 USDT
|
||||
- support_4h = 1900 USDT
|
||||
|
||||
```python
|
||||
sl_price = 1900 * 0.999 = 1898.1
|
||||
sl_ratio = (1898.1 / 2000) - 1.0 = -0.0595(约 -5.95%)
|
||||
```
|
||||
|
||||
即:止损触发点在当前价格的 5.95% 下方。
|
||||
|
||||
---
|
||||
|
||||
## 十、退出原因分类(理解 freqtrade 的逻辑)
|
||||
|
||||
| 退出原因 | 触发条件 | v1.6 ETH 全周期 |
|
||||
|----------|----------|-----------------|
|
||||
| `stop_loss` | 价格触及 `custom_stoploss` 返回的价格,且 current_profit < 0 | 73 笔,0% 胜率 |
|
||||
| `trailing_stop_loss` | 价格从高点回落,触及之前计算的止损价,且有过盈利 | 71 笔,67.6% 胜率 |
|
||||
| `exit_signal` | `populate_exit_trend` 返回 exit=1 | 7 笔,71.4% 胜率 |
|
||||
| `force_exit` | 回测结束强制平仓 | 1 笔,100% |
|
||||
|
||||
**`stop_loss` 和 `trailing_stop_loss` 的本质区别:**
|
||||
|
||||
- `stop_loss`:交易从入场到退出**从未产生过盈利**。价格一直往不利方向走,直到触发止损。
|
||||
- `trailing_stop_loss`:交易曾经**有过盈利**,后来价格回落,触及追踪止损位退出。
|
||||
|
||||
**这说明了什么?**
|
||||
|
||||
73 笔 `stop_loss` = 73 笔入场后价格立即向不利方向走的交易。
|
||||
|
||||
这些交易**入场位是错的**,或者**在错误的时机做了正确的方向**。这是 v1.6 最核心的问题,也是下一步优化的主攻方向。
|
||||
|
||||
---
|
||||
|
||||
## 十一、已知问题和局限性
|
||||
|
||||
### 问题 1:`stop_loss` 胜率 0%(最严重)
|
||||
- 表现:73 笔 stop_loss 退出,全部亏损
|
||||
- 根本原因:入场后价格立即反向,说明入场位质量不高
|
||||
- 可能方向:更严格的入场过滤、更好的时机判断
|
||||
|
||||
### 问题 2:支撑位识别的逻辑漏洞
|
||||
- `nearest_support = sl_prices[-1]` 直接取最近的 Swing Low,可能在当前价格之上
|
||||
- 例如:价格在 2000,但最近 Swing Low 是 2100(价格刚从 2100 跌下来),这时支撑 = 2100 > 2000,止损价在当前价格上方,逻辑矛盾
|
||||
- `long_stop_dist > 0.003` 一定程度上过滤了这种情况,但不完全
|
||||
|
||||
### 问题 3:出场逻辑太粗糙
|
||||
- 只看 D1 趋势是否反转
|
||||
- D1 趋势切换很慢,大多数交易靠止损退出,而非出场信号
|
||||
- 可以考虑增加 4H 结构破坏作为出场信号
|
||||
|
||||
### 问题 4:市场环境依赖
|
||||
- 趋势市(2023-2024):表现优异
|
||||
- 震荡市(2025 YTD BTC):表现差
|
||||
- 没有"市场环境过滤器",在震荡市会频繁入场并被止损
|
||||
|
||||
### 问题 5:`fillna(False)` 的 FutureWarning
|
||||
- 技术性问题,不影响结果,但需要修复(pandas 未来版本会报错)
|
||||
|
||||
---
|
||||
|
||||
## 十二、数据流的完整路径
|
||||
|
||||
一笔做多交易的完整生命周期:
|
||||
|
||||
```
|
||||
1. D1 数据 → _detect_swing_points() → _build_structure()
|
||||
→ 输出 trend_up_1d = True (日线上升趋势确认)
|
||||
|
||||
2. 4H 数据 → _detect_swing_points() → _build_structure()
|
||||
→ 输出 support_4h = 1900, resistance_4h = 2100
|
||||
→ 输出 in_demand_4h = True (价格在需求区)
|
||||
→ v1.6: 检查 support_alive_4h = True (支撑最近被测试过)
|
||||
|
||||
3. 1H 数据 → _detect_candle_patterns()
|
||||
→ 输出 bullish_signal = True (出现看涨 Pin Bar 或吞没)
|
||||
|
||||
4. populate_entry_trend() 汇总所有条件
|
||||
→ 全部满足 + 冷却期过了 → enter_long = 1 → 下单做多
|
||||
|
||||
5. 持仓期间,每根 1H K 线:
|
||||
→ custom_stoploss() 被调用
|
||||
→ 读取最新 support_4h
|
||||
→ 计算止损价 = support_4h * 0.999
|
||||
→ 止损位随 support_4h 上移(追踪效果)
|
||||
|
||||
6. 退出:
|
||||
→ 价格创新高后回落触及止损 → trailing_stop_loss 退出
|
||||
→ 或价格入场后就下跌 → stop_loss 退出
|
||||
→ 或 D1 趋势反转 → exit_signal 退出
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 十三、优化的可能方向(供后续参考)
|
||||
|
||||
基于以上分析,以下是最有价值的优化方向(按优先级排序):
|
||||
|
||||
**优先级 A:解决 stop_loss 0% 胜率**
|
||||
1. 分析 73 笔 stop_loss 交易的特征(何时入场?市场处于什么状态?)
|
||||
2. 增加入场质量过滤(例如:要求 4H 也是上升趋势、要求成交量确认)
|
||||
3. 改进 Swing Point 识别(例如:要求支撑位被测试 2 次以上)
|
||||
|
||||
**优先级 B:增加市场环境过滤**
|
||||
1. 识别"震荡市"(例如:最近 N 根 4H bar 内,没有明确的 HH/HL 序列)
|
||||
2. 在震荡市中停止交易,只在趋势市中工作
|
||||
|
||||
**优先级 C:改进出场逻辑**
|
||||
1. 将出场信号细化到 4H 级别(4H 结构破坏时退出,而不等 D1 反转)
|
||||
2. 可以大幅减少 stop_loss 次数,让更多交易变成 exit_signal 或 trailing_stop_loss
|
||||
|
||||
---
|
||||
|
||||
*文档基于 `structure_flow_strategy_v1_6.py` 代码,v1.6 版本(2026-06-07)*
|
||||
Reference in New Issue
Block a user