From 757b7033fe974a5c17c8bf7152cecea1f62d54cb Mon Sep 17 00:00:00 2001 From: 27942 <1313123@342> Date: Tue, 3 Feb 2026 23:27:14 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96bitmart=E4=BA=A4=E6=98=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 1111 | 10 +- bitmart/三分之一策略-5分钟交易.py | 162 +++++++++++++----------------- 2 files changed, 78 insertions(+), 94 deletions(-) diff --git a/1111 b/1111 index d2dcb89..fd3cbe4 100644 --- a/1111 +++ b/1111 @@ -24,8 +24,8 @@ Abc12345678 基于前一根有效 K 线(实体 ≥ 0.1): -做多触发价 = 当前 k 线开盘价 + 实体 / 5(收盘价向上 1/5 实体) -做空触发价 = 当前 k 线开盘价 - 实体 / 5(收盘价向下 1/5 实体) +做多触发价 = 当前 k 线开盘价 + 实体 / 3(收盘价向上 1/3 实体) +做空触发价 = 当前 k 线开盘价 - 实体 / 3(收盘价向下 1/3 实体) 若已有持仓,在 3 分钟 K 线的第一分钟可单独检测反手: 持空反手做多:价格涨到 开仓价 + 前一根实体 / 5 @@ -35,8 +35,10 @@ Abc12345678 反手信号, 当前这根线线跌倒了上一根的三分之一,我开了空,但是这根涨到了上一根 k 线的最高价格,上一根 k 线的上阴线涨幅大于 0.01%,反手做多 -第二个反手信号,当前这根做了多,上一根 k 线的上阴线涨幅大于 0.01%,当前这个根跌倒了上一根的开盘价格,反手做空 - + +反手信号: +反手做空,当前这根做多,上一根 k 线的上阴线涨幅大于 0.01%,当前这个根跌倒了上一根的k线的实体边,反手做空 +反手做多,当前这根做空,上一根 k 线的下阴线跌幅大于 0.01%,当前这个根涨到了上一根的k线的实体边,反手做多 diff --git a/bitmart/三分之一策略-5分钟交易.py b/bitmart/三分之一策略-5分钟交易.py index 4a52d23..f1b4540 100644 --- a/bitmart/三分之一策略-5分钟交易.py +++ b/bitmart/三分之一策略-5分钟交易.py @@ -1,12 +1,12 @@ """ BitMart 三分之一策略 — 5分钟K线交易 -策略规则(与 交易/bitmart-三分之一策略交易.py、回测数据-三分之一策略-5分钟精准版 一致): -1. 触发价格(基于前一根有效K线,实体>=0.1): - - 做多触发价 = 收盘价 + 实体/3(从收盘价往上涨1/3) - - 做空触发价 = 收盘价 - 实体/3(从收盘价往下跌1/3) +策略规则: +1. 触发价格(基于前一根有效K线实体>=0.1,使用当前K线开盘价): + - 做多触发价 = 当前K线开盘价 + 实体/3 + - 做空触发价 = 当前K线开盘价 - 实体/3 -2. 信号触发: +2. 信号触发(无持仓时): - 当前5分钟K线最高价 >= 做多触发价 → 做多信号 - 当前5分钟K线最低价 <= 做空触发价 → 做空信号 @@ -17,14 +17,11 @@ BitMart 三分之一策略 — 5分钟K线交易 4. 同根K线多空都触及时,用开盘价与触发价距离判断先后。 -5. 反手信号(基于上一根K线高低点+影线幅度): - - 持空反手做多:当前K线涨到上一根K线最高价,且上一根K线上影线涨幅 > 0.01% -> 平空反手开多 - - 持多反手做空:当前K线跌到上一根K线最低价,且上一根K线下影线跌幅 > 0.01% -> 平多反手开空 - (上影线 = high - max(open,close),上影线涨幅 = (上影线/开盘价)*100;下影线同理) - -6. 反手信号二(基于上一根开盘价+影线幅度): - - 持多反手做空:上一根K线上影线涨幅 > 0.01%,且当前K线跌到上一根开盘价 -> 平多反手开空 - - 持空反手做多:上一根K线下影线跌幅 > 0.01%,且当前K线涨到上一根开盘价 -> 平空反手开多 +5. 反手信号(有持仓时检测): + - 反手做空:当前持多,上一根K线上阴线涨幅 > 0.01%,当前K线跌到上一根K线的实体下边 -> 平多反手开空 + - 反手做多:当前持空,上一根K线下阴线跌幅 > 0.01%,当前K线涨到上一根K线的实体上边 -> 平空反手开多 + (上阴线 = high - max(open,close),上阴线涨幅 = (上阴线/开盘价)*100;下阴线同理) + (实体上边 = max(open,close),实体下边 = min(open,close)) """ import random import time @@ -48,7 +45,7 @@ ding_executor = ThreadPoolExecutor(max_workers=2, thread_name_prefix="dingtalk") class BitmartOneThirdStrategy: - """三分之一策略:触发价 = 收盘价 ± 实体/3,5分钟K线""" + """三分之一策略:触发价 = 当前K线开盘价 ± 实体/3,5分钟K线""" def __init__(self, bit_id): self.page: ChromiumPage | None = None @@ -100,18 +97,20 @@ class BitmartOneThirdStrategy: return i, prev return None, None - def get_one_third_levels(self, prev): + def get_one_third_levels(self, prev, curr): """ - 做多触发价 = 收盘价 + 实体/3 - 做空触发价 = 收盘价 - 实体/3 + 做多触发价 = 当前K线开盘价 + 实体/3 + 做空触发价 = 当前K线开盘价 - 实体/3 + 实体来自前一根有效K线 """ p_open = float(prev['open']) p_close = float(prev['close']) + curr_open = float(curr['open']) body = abs(p_open - p_close) if body < 0.001: return None, None - long_trigger = p_close + body / 3 - short_trigger = p_close - body / 3 + long_trigger = curr_open + body / 3 + short_trigger = curr_open - body / 3 return long_trigger, short_trigger def get_upper_shadow(self, candle): @@ -138,36 +137,19 @@ class BitmartOneThirdStrategy: return 0.0 return self.get_lower_shadow(candle) / o * 100 - def check_reverse_by_prev_high_low(self, kline_data): - """ - 反手信号:持空时当前K线涨到上一根最高价且上一根上影线涨幅>0.01% -> 反手做多; - 持多时当前K线跌到上一根最低价且上一根下影线跌幅>0.01% -> 反手做空。 - 使用紧邻的上一根K线(kline_data[-2]),非“有效实体”前一根。 - 返回:(方向 'long'|'short', 上一根K线) 或 (None, None) - """ - if len(kline_data) < 2: - return None, None - curr = kline_data[-1] - prev = kline_data[-2] - curr_high = float(curr['high']) - curr_low = float(curr['low']) - prev_high = float(prev['high']) - prev_low = float(prev['low']) + def get_body_upper_edge(self, candle): + """实体上边 = max(open, close)""" + return max(float(candle['open']), float(candle['close'])) - # 持空反手做多:当前涨到上一根最高价,且上一根上影线涨幅 > 0.01% - if self.start == -1: - if curr_high >= prev_high and self.upper_shadow_pct(prev) > self.min_shadow_pct: - return 'long', prev - # 持多反手做空:当前跌到上一根最低价,且上一根下影线跌幅 > 0.01% - if self.start == 1: - if curr_low <= prev_low and self.lower_shadow_pct(prev) > self.min_shadow_pct: - return 'short', prev - return None, None + def get_body_lower_edge(self, candle): + """实体下边 = min(open, close)""" + return min(float(candle['open']), float(candle['close'])) - def check_reverse_by_prev_open(self, kline_data): + def check_reverse_signal(self, kline_data): """ - 反手信号二:持多时上一根上影线涨幅>0.01%且当前K线跌到上一根开盘价 -> 反手做空; - 持空时上一根下影线跌幅>0.01%且当前K线涨到上一根开盘价 -> 反手做多。 + 反手信号(有持仓时检测): + - 反手做空:当前持多,上一根K线上阴线涨幅 > 0.01%,当前K线跌到上一根K线的实体下边 + - 反手做多:当前持空,上一根K线下阴线跌幅 > 0.01%,当前K线涨到上一根K线的实体上边 使用紧邻的上一根K线(kline_data[-2])。 返回:(方向 'long'|'short', 上一根K线) 或 (None, None) """ @@ -177,22 +159,23 @@ class BitmartOneThirdStrategy: prev = kline_data[-2] curr_high = float(curr['high']) curr_low = float(curr['low']) - prev_open = float(prev['open']) + prev_body_upper = self.get_body_upper_edge(prev) # 实体上边 + prev_body_lower = self.get_body_lower_edge(prev) # 实体下边 - # 持多反手做空:上一根上影线涨幅>0.01%,当前跌到上一根开盘价 + # 持多反手做空:上一根上阴线涨幅>0.01%,当前跌到上一根实体下边 if self.start == 1: - if self.upper_shadow_pct(prev) > self.min_shadow_pct and curr_low <= prev_open: + if self.upper_shadow_pct(prev) > self.min_shadow_pct and curr_low <= prev_body_lower: return 'short', prev - # 持空反手做多:上一根下影线跌幅>0.01%,当前涨到上一根开盘价 + # 持空反手做多:上一根下阴线跌幅>0.01%,当前涨到上一根实体上边 if self.start == -1: - if self.lower_shadow_pct(prev) > self.min_shadow_pct and curr_high >= prev_open: + if self.lower_shadow_pct(prev) > self.min_shadow_pct and curr_high >= prev_body_upper: return 'long', prev return None, None def check_realtime_trigger(self, kline_data): """ 检查当前5分钟K线是否触发信号。 - 做多触发价 = 前一根收盘价 + 实体/3,做空 = 收盘价 - 实体/3。 + 做多触发价 = 当前K线开盘价 + 实体/3,做空 = 当前K线开盘价 - 实体/3。 同根多空都触发时用开盘价与触发价距离判断先后。 返回:(方向, 触发价格, 有效前一根K线, 当前K线) 或 (None, None, None, None) """ @@ -209,7 +192,7 @@ class BitmartOneThirdStrategy: if prev is None: return None, None, None, None - long_trigger, short_trigger = self.get_one_third_levels(prev) + long_trigger, short_trigger = self.get_one_third_levels(prev, curr) if long_trigger is None: return None, None, None, None @@ -457,12 +440,13 @@ class BitmartOneThirdStrategy: try: kline_data = self.get_klines() - if not kline_data or len(kline_data) < 3: + if not kline_data or len(kline_data) < 2: logger.warning("K线数据不足,等待重试...") time.sleep(self.check_interval) continue curr = kline_data[-1] + prev = kline_data[-2] curr_time_str = datetime.datetime.fromtimestamp(curr['id']).strftime('%H:%M:%S') if not self.get_position_status(): @@ -470,42 +454,40 @@ class BitmartOneThirdStrategy: curr_kline_id = curr['id'] - # 优先检测:反手信号一(涨到上根最高/跌到上根最低 + 上/下影线>0.01%) - rev_dir, rev_prev = self.check_reverse_by_prev_high_low(kline_data) - rev_type = "一" - if not rev_dir: - # 反手信号二(跌到/涨到上根开盘价 + 上/下影线>0.01%) - rev_dir, rev_prev = self.check_reverse_by_prev_open(kline_data) - rev_type = "二" - if rev_dir and self.last_trade_kline_id != curr_kline_id: - balance = self.get_available_balance() - trade_size = (balance or 0) * self.risk_percent - if rev_prev is not None: - up_pct = self.upper_shadow_pct(rev_prev) - low_pct = self.lower_shadow_pct(rev_prev) - logger.info(f"{'='*50}") - if rev_type == "一": - logger.info(f"🔄 反手信号{rev_type}({rev_dir}):当前K线触及上一根{'最高' if rev_dir == 'long' else '最低'}价") + # 有持仓时优先检测反手信号 + if self.start != 0: + rev_dir, rev_prev = self.check_reverse_signal(kline_data) + if rev_dir and self.last_trade_kline_id != curr_kline_id: + balance = self.get_available_balance() + trade_size = (balance or 0) * self.risk_percent + if rev_prev is not None: + up_pct = self.upper_shadow_pct(rev_prev) + low_pct = self.lower_shadow_pct(rev_prev) + prev_body_upper = self.get_body_upper_edge(rev_prev) + prev_body_lower = self.get_body_lower_edge(rev_prev) + logger.info(f"{'='*50}") + if rev_dir == 'long': + logger.info(f"🔄 反手信号({rev_dir}):当前K线涨到上一根实体上边={prev_body_upper:.2f}") + else: + logger.info(f"🔄 反手信号({rev_dir}):当前K线跌到上一根实体下边={prev_body_lower:.2f}") + logger.info(f" 上一根 上阴线涨幅={up_pct:.3f}% 下阴线跌幅={low_pct:.3f}%") + logger.info(f"{'='*50}") + if rev_dir == 'long': + logger.info("📈 平空反手开多") + self.平仓() + time.sleep(1) + self.开单(marketPriceLongOrder=1, size=trade_size) else: - logger.info(f"🔄 反手信号{rev_type}({rev_dir}):当前K线触及上一根开盘价 O={rev_prev['open']:.2f}") - logger.info(f" 上一根 上影线涨幅={up_pct:.3f}% 下影线跌幅={low_pct:.3f}%") - logger.info(f"{'='*50}") - if rev_dir == 'long': - logger.info("📈 平空反手开多") - self.平仓() - time.sleep(1) - self.开单(marketPriceLongOrder=1, size=trade_size) - else: - logger.info("📉 平多反手开空") - self.平仓() - time.sleep(1) - self.开单(marketPriceLongOrder=-1, size=trade_size) - self.last_trade_kline_id = curr_kline_id - self.last_trigger_kline_id = curr_kline_id - self.last_trigger_direction = rev_dir - self.get_position_status() - time.sleep(self.check_interval) - continue + logger.info("📉 平多反手开空") + self.平仓() + time.sleep(1) + self.开单(marketPriceLongOrder=-1, size=trade_size) + self.last_trade_kline_id = curr_kline_id + self.last_trigger_kline_id = curr_kline_id + self.last_trigger_direction = rev_dir + self.get_position_status() + time.sleep(self.check_interval) + continue direction, trigger_price, valid_prev, curr_kline = self.check_realtime_trigger(kline_data) @@ -531,7 +513,7 @@ class BitmartOneThirdStrategy: logger.info(f"{'='*50}") logger.info(f"🚨 检测到{direction}信号 触发价={trigger_price:.2f}") logger.info(f" 有效前一根[{prev_time}] {prev_type} 实体={prev_body:.2f}") - logger.info(f" 当前5分钟K线 H={curr_kline['high']:.2f} L={curr_kline['low']:.2f} C={curr_kline['close']:.2f}") + logger.info(f" 当前5分钟K线 O={curr_kline['open']:.2f} H={curr_kline['high']:.2f} L={curr_kline['low']:.2f} C={curr_kline['close']:.2f}") logger.info(f" 当前持仓: {self.start} (1=多 -1=空 0=无)") balance = self.get_available_balance()