diff --git a/open_fifth_strategy/README.md b/open_fifth_strategy/README.md index 7fc67ad..7bf472a 100644 --- a/open_fifth_strategy/README.md +++ b/open_fifth_strategy/README.md @@ -14,10 +14,12 @@ - 当前 K 线最高价 ≥ 做多触发价 → 做多信号 - 当前 K 线最低价 ≤ 做空触发价 → 做空信号 -### 第一分钟反手(若已有持仓) +### 前1分30秒反手(若已有持仓) +- 3分钟K线的**前1分30秒**内若出现反手信号 → 平仓开反手 - **持空反手做多**:价格涨到 开仓价 + 前一根实体/5 - **持多反手做空**:价格跌到 开仓价 - 前一根实体/5 +- 检测窗口:使用前2根1分钟K线(覆盖 0:00~2:00,包含 0:00~1:30) ### 与原始五分之一策略的区别 diff --git a/open_fifth_strategy/config.py b/open_fifth_strategy/config.py index 3e986b9..232d9ec 100644 --- a/open_fifth_strategy/config.py +++ b/open_fifth_strategy/config.py @@ -29,5 +29,9 @@ RISK_PERCENT = 0.01 # 每次开仓占用可用余额的比例 # 反手信号价格容差(美元) REVERSE_PRICE_TOLERANCE = 2.0 +# 反手信号检测窗口:3分钟K线的「前1分30秒」内出现反手信号则平仓反手 +# 使用前2根1分钟K线近似(覆盖 0:00~2:00,包含 0:00~1:30) +REVERSE_WINDOW_1M_BARS = 2 + # 比特浏览器ID(用于网页下单) BIT_ID = "f2320f57e24c45529a009e1541e25961" diff --git a/open_fifth_strategy/main.py b/open_fifth_strategy/main.py index a8ca0fc..07701a5 100644 --- a/open_fifth_strategy/main.py +++ b/open_fifth_strategy/main.py @@ -11,7 +11,8 @@ BitMart 基于开盘价的五分之一策略交易 - 当前K线最高价 >= 做多触发价 → 做多信号 - 当前K线最低价 <= 做空触发价 → 做空信号 -3. 第一分钟反手(若已有持仓): +3. 前1分30秒反手(若已有持仓): + - 3分钟K线的前1分30秒内若出现反手信号,则平仓开反手 - 持空反手做多:价格涨到 开仓价 + 前一根实体/5 - 持多反手做空:价格跌到 开仓价 - 前一根实体/5 @@ -50,6 +51,7 @@ from open_fifth_strategy.config import ( OPEN_TYPE, RISK_PERCENT, REVERSE_PRICE_TOLERANCE, + REVERSE_WINDOW_1M_BARS, BIT_ID, ) @@ -82,6 +84,7 @@ class OpenBasedFifthStrategy: self.open_type = OPEN_TYPE self.risk_percent = RISK_PERCENT self.reverse_price_tolerance = REVERSE_PRICE_TOLERANCE + self.reverse_window_1m_bars = REVERSE_WINDOW_1M_BARS self.last_trigger_kline_id = None self.last_trigger_direction = None @@ -89,7 +92,7 @@ class OpenBasedFifthStrategy: self.entry_prev_body = None self.entry_price = None self.entry_kline_id = None - self.first_minute_reverse_executed = False + self.early_reverse_executed = False # ==================== 策略核心(基于开盘价)==================== @@ -171,21 +174,23 @@ class OpenBasedFifthStrategy: return "short" if d_short < d_long else "long" return None - def check_first_minute_reverse_signal(self, curr_kline, kline_data): + def check_early_reverse_signal(self, curr_kline, kline_data): """ - 第一分钟反手检测(与1111一致): + 前1分30秒反手检测(与1111一致): + - 3分钟K线的「前1分30秒」内若出现反手信号 → 平仓开反手 - 持空反手做多:价格涨到 开仓价 + 前一根实体/5 - 持多反手做空:价格跌到 开仓价 - 前一根实体/5 + - 使用前 N 根1分钟K线近似(REVERSE_WINDOW_1M_BARS=2 覆盖约 0:00~1:30) """ if self.start == 0: return None, None curr_kline_id = curr_kline["id"] if self.entry_kline_id != curr_kline_id: - self.first_minute_reverse_executed = False + self.early_reverse_executed = False self.entry_kline_id = curr_kline_id - if self.first_minute_reverse_executed: + if self.early_reverse_executed: return None, None entry_price = self.entry_price @@ -203,25 +208,28 @@ class OpenBasedFifthStrategy: reverse_offset = prev_body / 5 bars_1m = self.get_1m_bars_for_3m_bar(curr_kline) - if not bars_1m or len(bars_1m) < 1: + n_bars = min(self.reverse_window_1m_bars, len(bars_1m)) + if n_bars < 1: return None, None - first_1m = bars_1m[0] - first_1m_high = float(first_1m["high"]) - first_1m_low = float(first_1m["low"]) - first_1m_close = float(first_1m["close"]) + # 遍历前 N 根1分钟K线(覆盖前1分30秒),任一出现反手信号则触发 + for i in range(n_bars): + bar = bars_1m[i] + bar_high = float(bar["high"]) + bar_low = float(bar["low"]) + bar_close = float(bar["close"]) - if self.start == -1: - reverse_long_trigger = entry_price + reverse_offset - if first_1m_high >= reverse_long_trigger: - if first_1m_close >= reverse_long_trigger - self.reverse_price_tolerance: - return "long", reverse_long_trigger + if self.start == -1: + reverse_long_trigger = entry_price + reverse_offset + if bar_high >= reverse_long_trigger: + if bar_close >= reverse_long_trigger - self.reverse_price_tolerance: + return "long", reverse_long_trigger - elif self.start == 1: - reverse_short_trigger = entry_price - reverse_offset - if first_1m_low <= reverse_short_trigger: - if first_1m_close <= reverse_short_trigger + self.reverse_price_tolerance: - return "short", reverse_short_trigger + elif self.start == 1: + reverse_short_trigger = entry_price - reverse_offset + if bar_low <= reverse_short_trigger: + if bar_close <= reverse_short_trigger + self.reverse_price_tolerance: + return "short", reverse_short_trigger return None, None @@ -553,7 +561,7 @@ class OpenBasedFifthStrategy: # 第一分钟反手 if self.start != 0: - first_dir, first_trigger = self.check_first_minute_reverse_signal( + first_dir, first_trigger = self.check_early_reverse_signal( curr, kline_data ) if first_dir: @@ -569,7 +577,7 @@ class OpenBasedFifthStrategy: self.平仓() time.sleep(1) self.开单(marketPriceLongOrder=-1, size=trade_size) - self.first_minute_reverse_executed = True + self.early_reverse_executed = True self.last_trade_kline_id = curr_kline_id _, valid_prev = self.find_valid_prev_bar( kline_data, len(kline_data) - 1 @@ -634,7 +642,7 @@ class OpenBasedFifthStrategy: self.entry_price = trigger_price self.entry_prev_body = self.get_body_size(valid_prev) self.entry_kline_id = curr_kline_id - self.first_minute_reverse_executed = False + self.early_reverse_executed = False self.get_position_status() self._send_position_message(curr_kline) last_report_time = time.time()