代码结构优化

This commit is contained in:
ddrwode
2026-02-03 11:52:59 +08:00
parent 6af2458241
commit 784a2a3af3

View File

@@ -16,6 +16,15 @@ BitMart 三分之一策略 — 5分钟K线交易
- 同一根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线涨到上一根开盘价 -> 平空反手开多
"""
import random
import time
@@ -71,6 +80,7 @@ class BitmartOneThirdStrategy:
self.last_trigger_kline_id = None
self.last_trigger_direction = None
self.last_trade_kline_id = None
self.min_shadow_pct = 0.01 # 反手信号:上/下影线幅度需 > 0.01%
# ========================= 三分之一策略核心 =========================
@@ -104,6 +114,81 @@ class BitmartOneThirdStrategy:
short_trigger = p_close - body / 3
return long_trigger, short_trigger
def get_upper_shadow(self, candle):
"""上影线 = high - max(open, close)"""
o, c, h = float(candle['open']), float(candle['close']), float(candle['high'])
return h - max(o, c)
def get_lower_shadow(self, candle):
"""下影线 = min(open, close) - low"""
o, c, l = float(candle['open']), float(candle['close']), float(candle['low'])
return min(o, c) - l
def upper_shadow_pct(self, candle):
"""上影线涨幅 = (上影线/开盘价)*100"""
o = float(candle['open'])
if o <= 0:
return 0.0
return self.get_upper_shadow(candle) / o * 100
def lower_shadow_pct(self, candle):
"""下影线跌幅 = (下影线/开盘价)*100"""
o = float(candle['open'])
if o <= 0:
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'])
# 持空反手做多:当前涨到上一根最高价,且上一根上影线涨幅 > 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 check_reverse_by_prev_open(self, kline_data):
"""
反手信号二:持多时上一根上影线涨幅>0.01%且当前K线跌到上一根开盘价 -> 反手做空;
持空时上一根下影线跌幅>0.01%且当前K线涨到上一根开盘价 -> 反手做多。
使用紧邻的上一根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_open = float(prev['open'])
# 持多反手做空:上一根上影线涨幅>0.01%,当前跌到上一根开盘价
if self.start == 1:
if self.upper_shadow_pct(prev) > self.min_shadow_pct and curr_low <= prev_open:
return 'short', prev
# 持空反手做多:上一根下影线跌幅>0.01%,当前涨到上一根开盘价
if self.start == -1:
if self.lower_shadow_pct(prev) > self.min_shadow_pct and curr_high >= prev_open:
return 'long', prev
return None, None
def check_realtime_trigger(self, kline_data):
"""
检查当前5分钟K线是否触发信号。
@@ -383,6 +468,45 @@ class BitmartOneThirdStrategy:
if not self.get_position_status():
logger.warning("获取仓位失败,使用缓存")
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 '最低'}")
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
direction, trigger_price, valid_prev, curr_kline = self.check_realtime_trigger(kline_data)
if direction: