Merge remote-tracking branch 'origin/master'

# Conflicts:
#	交易/bitmart-三分之一策略交易.py
This commit is contained in:
Administrator
2026-02-01 01:25:29 +08:00
14 changed files with 15744 additions and 0 deletions

View File

@@ -0,0 +1,79 @@
# 自适应三分位趋势策略
优化版实盘策略:趋势过滤 + 动态阈值 + 信号确认 + 完整风险管理。
## 目录结构
- `config.py` - 策略参数(趋势模式、止损止盈、确认条件等)
- `indicators.py` - EMA、ATR 指标
- `data_fetcher.py` - **Bitmart 方式**拉取 5/15/60 分钟 K 线API 或 CSV
- `strategy_core.py` - 趋势判断、有效 K 线、动态触发价、信号确认
- `backtest.py` - 回测引擎(硬止损、止盈、移动止损、时间止损)
- `trade.py` - 实盘交易入口(拉数据 + 信号,开平仓需对接现有 Bitmart 下单逻辑)
- `data/` - 回测用 K 线 CSV可选无则 API 拉取)
## 回测(先出数据再回测)
在**项目根目录** `lm_code` 下执行:
```bash
# 使用 API 拉取数据并回测(会请求 Bitmart 接口)
python adaptive_third_strategy/backtest.py --start 2025-01-01 --end 2025-01-30 --capital 10000
# 仅用本地已有 CSV 回测(需先抓过数据)
python adaptive_third_strategy/backtest.py --start 2025-01-01 --end 2025-01-30 --no-api
```
数据会保存到 `adaptive_third_strategy/data/kline_5m.csv``kline_15m.csv``kline_60m.csv`
回测结果输出到控制台,交易明细保存到 `adaptive_third_strategy/backtest_trades.csv`
## 仅抓取数据Bitmart 方式)
`bitmart/回测.py``bitmart/抓取多周期K线.py` 相同的 API 调用方式:
```bash
cd adaptive_third_strategy && python -c "
from data_fetcher import fetch_multi_timeframe, save_klines_csv
import time, os
end_ts = int(time.time())
start_ts = end_ts - 30*24*3600
data = fetch_multi_timeframe(start_ts, end_ts, [5, 15, 60])
os.makedirs('data', exist_ok=True)
for step, klines in data.items():
save_klines_csv(klines, f'data/kline_{step}m.csv')
"
```
需在项目根目录 `lm_code` 下执行时,先 `import sys; sys.path.insert(0, '..')` 或使用:
```bash
python -c "
import sys, os
sys.path.insert(0, os.getcwd())
from adaptive_third_strategy.data_fetcher import fetch_multi_timeframe, save_klines_csv
import time
end_ts = int(time.time())
start_ts = end_ts - 30*24*3600
data = fetch_multi_timeframe(start_ts, end_ts, [5, 15, 60])
os.makedirs('adaptive_third_strategy/data', exist_ok=True)
for step, klines in data.items():
save_klines_csv(klines, f'adaptive_third_strategy/data/kline_{step}m.csv')
"
```
## 实盘
```bash
python adaptive_third_strategy/trade.py
```
当前 `trade.py` 只做:拉 5/15/60 数据、算信号、打日志/钉钉。实际开平仓需在 `run_loop` 里接入你现有的 Bitmart 下单方式(如 `交易/bitmart-三分之一策略交易.py` 的浏览器点击或 API 下单)。
## 策略要点
- **数据与周期**:主周期 5 分钟,趋势用 15 分钟 / 1 小时 EMA。
- **有效 K 线**:实体 ≥ max(ATR×0.1, 价格×0.05%)。
- **趋势过滤**:长期 1h EMA50/200中期 15m EMA20/50短期 5m 收盘 vs EMA9保守模式要求中期+短期一致。
- **动态触发**:波动率系数 clamp(实体/ATR, 0.3, 3.0),顺势方向更易触发。
- **信号确认**:收盘价、成交量、动量等至少满足 2 项。
- **风控**:硬止损 ATR×2、时间止损 3 根 K、移动止损盈利 1×ATR 后 0.5×ATR 跟踪)、止盈目标 1.5/3/5×ATR。

View File

@@ -0,0 +1,2 @@
# -*- coding: utf-8 -*-
"""自适应三分位趋势策略"""

View File

@@ -0,0 +1,464 @@
# -*- coding: utf-8 -*-
"""
自适应三分位趋势策略 - 回测引擎
使用 Bitmart 方式获取数据API 或 CSV含硬止损、分批止盈、移动止损、时间止损
"""
import os
import sys
import csv
import datetime
from typing import List, Dict, Optional, Tuple
# 使用 UTC 时区,避免 utcfromtimestamp 弃用警告
def _utc_dt(ts):
if hasattr(datetime, "timezone") and hasattr(datetime.timezone, "utc"):
return datetime.datetime.fromtimestamp(ts, tz=datetime.timezone.utc)
return datetime.datetime.utcfromtimestamp(ts)
try:
from loguru import logger
except ImportError:
import logging
logger = logging.getLogger(__name__)
ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
if ROOT_DIR not in sys.path:
sys.path.insert(0, ROOT_DIR)
from adaptive_third_strategy.config import (
STEP_5M,
STEP_15M,
STEP_60M,
ATR_PERIOD,
EMA_SHORT,
EMA_MID_FAST,
EMA_MID_SLOW,
EMA_LONG_FAST,
EMA_LONG_SLOW,
STOP_LOSS_ATR_MULT,
TIME_STOP_BARS,
TRAIL_START_ATR,
TRAIL_ATR_MULT,
TP1_ATR,
TP2_ATR,
TP3_ATR,
TP1_RATIO,
TP2_RATIO,
TP3_RATIO,
MIN_BARS_SINCE_ENTRY,
SAME_KLINE_NO_REVERSE,
REVERSE_BREAK_MULT,
REVERSE_LOSS_ATR,
MAX_POSITION_PERCENT,
BASE_POSITION_PERCENT,
CONTRACT_SIZE,
FEE_RATE,
FEE_FIXED,
FEE_FIXED_BACKTEST,
MIN_BARS_BETWEEN_TRADES,
SLIPPAGE_POINTS,
)
from adaptive_third_strategy.indicators import get_ema_atr_from_klines, align_higher_tf_ema
from adaptive_third_strategy.strategy_core import (
check_trigger,
get_body_size,
build_volume_ma,
)
from adaptive_third_strategy.data_fetcher import (
fetch_multi_timeframe,
load_klines_csv,
save_klines_csv,
)
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
def ensure_data(
start_time: int,
end_time: int,
data_dir: str,
use_api: bool = True,
api_key: str = "",
secret_key: str = "",
) -> Tuple[List[Dict], List[Dict], List[Dict]]:
"""
确保有 5/15/60 分钟数据。若 data_dir 下已有 CSV 则加载,否则用 API 拉取并保存。
use_api=False 时仅从 CSV 加载(需事先抓取)。
"""
data_dir = data_dir or os.path.join(SCRIPT_DIR, "data")
os.makedirs(data_dir, exist_ok=True)
paths = {
5: os.path.join(data_dir, "kline_5m.csv"),
15: os.path.join(data_dir, "kline_15m.csv"),
60: os.path.join(data_dir, "kline_60m.csv"),
}
k5 = load_klines_csv(paths[5])
k15 = load_klines_csv(paths[15])
k60 = load_klines_csv(paths[60])
need_fetch = not k5 or not k15 or not k60
if need_fetch and use_api:
from adaptive_third_strategy.data_fetcher import DEFAULT_API_KEY, DEFAULT_SECRET_KEY, DEFAULT_MEMO
key = api_key or DEFAULT_API_KEY
sec = secret_key or DEFAULT_SECRET_KEY
data = fetch_multi_timeframe(start_time, end_time, [5, 15, 60], key, sec, DEFAULT_MEMO)
k5, k15, k60 = data[5], data[15], data[60]
for step, kl in [(5, k5), (15, k15), (60, k60)]:
save_klines_csv(kl, paths[step])
# 按时间范围过滤end_time 若为次日 0 点则用 < 以只含 end 日及之前)
k5 = [x for x in k5 if start_time <= x["id"] < end_time]
k15 = [x for x in k15 if start_time <= x["id"] < end_time]
k60 = [x for x in k60 if start_time <= x["id"] < end_time]
k5.sort(key=lambda x: x["id"])
k15.sort(key=lambda x: x["id"])
k60.sort(key=lambda x: x["id"])
return k5, k15, k60
def run_backtest(
klines_5m: List[Dict],
klines_15m: List[Dict],
klines_60m: List[Dict],
initial_capital: float = 10000.0,
use_stop_loss: bool = True,
use_take_profit: bool = True,
use_trailing_stop: bool = True,
use_time_stop: bool = True,
fixed_margin_usdt: Optional[float] = None,
leverage: Optional[float] = None,
deduct_fee: bool = True,
) -> Tuple[List[Dict], Dict, List[Dict]]:
"""
回测主循环。
- 若指定 fixed_margin_usdt 与 leverage则每笔开仓名义价值 = fixed_margin_usdt * leverage如 50U 一百倍 = 5000U
- deduct_fee=False 时不扣手续费,总盈利 = 所有 money_pnl 之和。
"""
if len(klines_5m) < ATR_PERIOD + 50:
logger.warning("5分钟K线数量不足")
return [], {}, klines_5m
ema_5m, atr_5m = get_ema_atr_from_klines(klines_5m, EMA_SHORT, ATR_PERIOD)
ema_15m_align = align_higher_tf_ema(klines_5m, klines_15m, EMA_MID_FAST, EMA_MID_SLOW)
ema_60m_align = align_higher_tf_ema(klines_5m, klines_60m, EMA_LONG_FAST, EMA_LONG_SLOW)
volume_ma = build_volume_ma(klines_5m)
trades: List[Dict] = []
position: Optional[Dict] = None
last_trade_bar_idx: Optional[int] = None
last_close_bar_idx: Optional[int] = None
equity_curve: List[float] = [initial_capital]
capital = initial_capital
# 每笔固定名义价值USDT50U 一百倍 = 5000
fixed_notional = (fixed_margin_usdt * leverage) if (fixed_margin_usdt is not None and leverage is not None) else None
use_fee = deduct_fee
fee_fixed = 0 if not use_fee else (FEE_FIXED_BACKTEST if FEE_FIXED_BACKTEST is not None else FEE_FIXED)
def _size_usdt(cap: float) -> float:
if fixed_notional is not None:
return fixed_notional
return min(cap * MAX_POSITION_PERCENT, cap * BASE_POSITION_PERCENT)
def _fee(sz: float) -> float:
return 0 if not use_fee else (fee_fixed + sz * FEE_RATE * 2)
for idx in range(ATR_PERIOD, len(klines_5m)):
just_reversed = False
curr = klines_5m[idx]
bar_id = curr["id"]
high, low, close = float(curr["high"]), float(curr["low"]), float(curr["close"])
atr_val = atr_5m[idx]
if atr_val is None or atr_val <= 0:
equity_curve.append(capital)
continue
# ---------- 持仓管理:止损 / 止盈 / 移动止损 / 时间止损 ----------
if position is not None:
pos_dir = position["direction"]
entry_price = position["entry_price"]
entry_idx = position["entry_bar_idx"]
entry_atr = position["entry_atr"]
stop_price = position.get("stop_price")
trail_activated = position.get("trail_activated", False)
exit_reason = None
exit_price = close
if pos_dir == "long":
# 硬止损
if use_stop_loss and stop_price is not None and low <= stop_price:
exit_price = min(stop_price, high)
exit_reason = "stop_loss"
# 止盈(简化:首次触及任一目标即全平)
elif use_take_profit:
tp1 = entry_price + entry_atr * TP1_ATR
tp2 = entry_price + entry_atr * TP2_ATR
tp3 = entry_price + entry_atr * TP3_ATR
if high >= tp3:
exit_price = tp3
exit_reason = "tp3"
elif high >= tp2:
exit_price = tp2
exit_reason = "tp2"
elif high >= tp1:
exit_price = tp1
exit_reason = "tp1"
# 移动止损
if use_trailing_stop and not exit_reason:
if close >= entry_price + entry_atr * TRAIL_START_ATR:
trail_activated = True
position["trail_activated"] = True
trail_stop = close - entry_atr * TRAIL_ATR_MULT
if low <= trail_stop:
exit_price = trail_stop
exit_reason = "trail_stop"
# 时间止损
if use_time_stop and not exit_reason and (idx - entry_idx) >= TIME_STOP_BARS:
if close <= entry_price:
exit_price = close
exit_reason = "time_stop"
else:
if use_stop_loss and stop_price is not None and high >= stop_price:
exit_price = max(stop_price, low)
exit_reason = "stop_loss"
elif use_take_profit:
tp1 = entry_price - entry_atr * TP1_ATR
tp2 = entry_price - entry_atr * TP2_ATR
tp3 = entry_price - entry_atr * TP3_ATR
if low <= tp3:
exit_price = tp3
exit_reason = "tp3"
elif low <= tp2:
exit_price = tp2
exit_reason = "tp2"
elif low <= tp1:
exit_price = tp1
exit_reason = "tp1"
if use_trailing_stop and not exit_reason:
if close <= entry_price - entry_atr * TRAIL_START_ATR:
trail_activated = True
position["trail_activated"] = True
trail_stop = close + entry_atr * TRAIL_ATR_MULT
if high >= trail_stop:
exit_price = trail_stop
exit_reason = "trail_stop"
if use_time_stop and not exit_reason and (idx - entry_idx) >= TIME_STOP_BARS:
if close >= entry_price:
exit_price = close
exit_reason = "time_stop"
if exit_reason:
# 平仓
if pos_dir == "long":
point_pnl = exit_price - entry_price
else:
point_pnl = entry_price - exit_price
size_usdt = position.get("size_usdt", _size_usdt(capital))
contract_val = CONTRACT_SIZE / entry_price
money_pnl = point_pnl / entry_price * size_usdt
fee = _fee(size_usdt)
net = money_pnl - fee
capital += net
trades.append({
"direction": "做多" if pos_dir == "long" else "做空",
"entry_time": _utc_dt(position["entry_time"]),
"exit_time": _utc_dt(bar_id),
"entry_price": entry_price,
"exit_price": exit_price,
"point_pnl": point_pnl,
"money_pnl": money_pnl,
"fee": fee,
"net_profit": net,
"exit_reason": exit_reason,
"hold_bars": idx - entry_idx,
})
position = None
last_close_bar_idx = idx
equity_curve.append(capital)
continue
# ---------- 信号检测 ----------
direction, trigger_price, valid_prev_idx, valid_prev = check_trigger(
klines_5m, idx, atr_5m, ema_5m, ema_15m_align, ema_60m_align, volume_ma, use_confirm=True
)
if direction is None:
equity_curve.append(capital)
continue
if SAME_KLINE_NO_REVERSE and last_trade_bar_idx == idx:
equity_curve.append(capital)
continue
if position is not None:
if direction == position["direction"]:
equity_curve.append(capital)
continue
# 反手条件
bars_since = idx - position["entry_bar_idx"]
if bars_since < MIN_BARS_SINCE_ENTRY:
equity_curve.append(capital)
continue
entry_atr_pos = position.get("entry_atr") or atr_val
pos_loss_atr = (position["entry_price"] - close) / entry_atr_pos if position["direction"] == "long" else (close - position["entry_price"]) / entry_atr_pos
if pos_loss_atr < REVERSE_LOSS_ATR:
# 可选:反向突破幅度 > 实体/2 才反手
equity_curve.append(capital)
continue
# 先平仓再开仓(下面统一开仓)
# 简化:这里直接平仓记一笔,再开新仓
exit_price = close
if position["direction"] == "long":
point_pnl = exit_price - position["entry_price"]
else:
point_pnl = position["entry_price"] - exit_price
size_usdt = position.get("size_usdt", _size_usdt(capital))
money_pnl = point_pnl / position["entry_price"] * size_usdt
fee = _fee(size_usdt)
net = money_pnl - fee
capital += net
trades.append({
"direction": "做多" if position["direction"] == "long" else "做空",
"entry_time": _utc_dt(position["entry_time"]),
"exit_time": _utc_dt(bar_id),
"entry_price": position["entry_price"],
"exit_price": exit_price,
"point_pnl": point_pnl,
"money_pnl": money_pnl,
"fee": fee,
"net_profit": net,
"exit_reason": "reverse",
"hold_bars": idx - position["entry_bar_idx"],
})
position = None
last_close_bar_idx = idx
just_reversed = True
# ---------- 开仓 ----------
# 反手后本 K 线允许开仓;否则需间隔 MIN_BARS_BETWEEN_TRADES 根
if not just_reversed and last_close_bar_idx is not None and (idx - last_close_bar_idx) < MIN_BARS_BETWEEN_TRADES:
equity_curve.append(capital)
continue
just_reversed = False
size_usdt = _size_usdt(capital)
if size_usdt <= 0:
equity_curve.append(capital)
continue
stop_price = None
if direction == "long":
stop_price = trigger_price - atr_val * STOP_LOSS_ATR_MULT
else:
stop_price = trigger_price + atr_val * STOP_LOSS_ATR_MULT
position = {
"direction": direction,
"entry_price": trigger_price,
"entry_time": bar_id,
"entry_bar_idx": idx,
"entry_atr": atr_val,
"stop_price": stop_price,
"size_usdt": size_usdt,
"closed_ratio": 0,
"trail_activated": False,
}
last_trade_bar_idx = idx
equity_curve.append(capital)
# 尾仓
if position is not None:
last_bar = klines_5m[-1]
exit_price = float(last_bar["close"])
pos_dir = position["direction"]
entry_price = position["entry_price"]
if pos_dir == "long":
point_pnl = exit_price - entry_price
else:
point_pnl = entry_price - exit_price
size_usdt = position.get("size_usdt", _size_usdt(capital))
money_pnl = point_pnl / entry_price * size_usdt
fee = _fee(size_usdt)
net = money_pnl - fee
capital += net
trades.append({
"direction": "做多" if pos_dir == "long" else "做空",
"entry_time": _utc_dt(position["entry_time"]),
"exit_time": _utc_dt(last_bar["id"]),
"entry_price": entry_price,
"exit_price": exit_price,
"point_pnl": point_pnl,
"money_pnl": money_pnl,
"fee": fee,
"net_profit": net,
"exit_reason": "tail",
"hold_bars": len(klines_5m) - 1 - position["entry_bar_idx"],
})
# 统计
total_net = sum(t["net_profit"] for t in trades)
total_gross = sum(t["money_pnl"] for t in trades)
total_fee = sum(t["fee"] for t in trades)
win_count = len([t for t in trades if t["net_profit"] > 0])
stats = {
"total_trades": len(trades),
"win_count": win_count,
"win_rate": (win_count / len(trades) * 100) if trades else 0,
"total_gross_profit": total_gross,
"total_fee": total_fee,
"total_net_profit": total_net,
"final_capital": capital,
"max_drawdown": 0,
"max_drawdown_pct": 0,
}
peak = initial_capital
for eq in equity_curve:
peak = max(peak, eq)
dd = peak - eq
if peak > 0:
stats["max_drawdown"] = max(stats["max_drawdown"], dd)
stats["max_drawdown_pct"] = max(stats["max_drawdown_pct"], dd / peak * 100)
return trades, stats, klines_5m
def main():
import argparse
parser = argparse.ArgumentParser(description="自适应三分位趋势策略回测")
parser.add_argument("--start", default="2025-01-01", help="开始日期 YYYY-MM-DD")
parser.add_argument("--end", default="2025-12-31", help="结束日期,默认 2025-12-31")
parser.add_argument("--data-dir", default=None, help="数据目录,默认 adaptive_third_strategy/data")
parser.add_argument("--no-api", action="store_true", help="不从 API 拉取,仅用本地 CSV")
parser.add_argument("--capital", type=float, default=10000, help="初始资金(按比例开仓时用)")
parser.add_argument("--fixed-margin", type=float, default=None, help="每笔固定保证金 USDT如 50")
parser.add_argument("--leverage", type=float, default=None, help="杠杆倍数,如 100")
parser.add_argument("--no-fee", action="store_true", help="不扣手续费,只算总盈利")
args = parser.parse_args()
start_dt = datetime.datetime.strptime(args.start, "%Y-%m-%d")
if args.end:
end_dt = datetime.datetime.strptime(args.end, "%Y-%m-%d")
# 包含 end 日全天:取次日 0 点前一刻,这样 id < end_ts 的 K 线都含在内
end_ts = int((end_dt + datetime.timedelta(days=1)).timestamp())
else:
end_ts = int(datetime.datetime.utcnow().timestamp())
start_ts = int(start_dt.timestamp())
data_dir = args.data_dir or os.path.join(SCRIPT_DIR, "data")
k5, k15, k60 = ensure_data(start_ts, end_ts, data_dir, use_api=not args.no_api)
if not k5:
logger.error("无 5 分钟数据,请先抓取或开启 --api")
return
logger.info(f"5m={len(k5)} 15m={len(k15)} 60m={len(k60)}")
trades, stats, _ = run_backtest(
k5, k15, k60,
initial_capital=args.capital,
fixed_margin_usdt=args.fixed_margin,
leverage=args.leverage,
deduct_fee=not args.no_fee,
)
logger.info(f"交易笔数: {stats['total_trades']} 胜率: {stats['win_rate']:.2f}% "
f"总盈利(未扣费): {stats['total_gross_profit']:.2f} USDT "
f"总手续费: {stats['total_fee']:.2f} 总净利润: {stats['total_net_profit']:.2f} "
f"最大回撤: {stats['max_drawdown']:.2f} ({stats['max_drawdown_pct']:.2f}%)")
out_csv = os.path.join(SCRIPT_DIR, "backtest_trades.csv")
if trades:
with open(out_csv, "w", newline="", encoding="utf-8") as f:
w = csv.DictWriter(f, fieldnames=["direction", "entry_time", "exit_time", "entry_price", "exit_price", "point_pnl", "money_pnl", "fee", "net_profit", "exit_reason", "hold_bars"])
w.writeheader()
for t in trades:
w.writerow({k: str(v) if isinstance(v, datetime.datetime) else v for k, v in t.items()})
logger.info(f"交易记录已保存: {out_csv}")
if __name__ == "__main__":
main()

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,97 @@
# -*- coding: utf-8 -*-
"""
自适应三分位趋势策略 - 配置参数
"""
# ========== 数据与周期 ==========
CONTRACT_SYMBOL = "ETHUSDT"
STEP_5M = 5
STEP_15M = 15
STEP_60M = 60
# 有效K线标准实体 >= max(ATR(20)*0.1, 最小波动阈值)
MIN_BODY_ATR_RATIO = 0.1
MIN_VOLATILITY_PERCENT = 0.0005 # 当前价格 × 0.05%
# ========== 趋势判断EMA周期 ==========
# 长期1小时 EMA(50) vs EMA(200)
EMA_LONG_FAST = 50
EMA_LONG_SLOW = 200
# 中期15分钟 EMA(20) vs EMA(50)
EMA_MID_FAST = 20
EMA_MID_SLOW = 50
# 短期5分钟 EMA(9)
EMA_SHORT = 9
# 交易模式aggressive / conservative / strict
TREND_MODE = "conservative"
# ========== 动态触发 ==========
ATR_PERIOD = 20
VOLATILITY_COEF_CLAMP = (0.3, 3.0) # 波动率系数范围
BASE_COEF = 0.33
# 趋势方向系数(顺势更易触发)
TREND_FAVOR_COEF = 0.8
TREND_AGAINST_COEF = 1.2
# ========== 信号确认(至少满足几项) ==========
CONFIRM_REQUIRED = 2
VOLUME_MA_PERIOD = 20
VOLUME_RATIO_THRESHOLD = 0.8 # 成交量 > 前20根均量 × 0.8
# ========== 风险管理 ==========
MAX_POSITION_PERCENT = 0.10 # 单笔最大 10%
BASE_POSITION_PERCENT = 0.02 # 基础仓位 2%
STOP_LOSS_ATR_MULT = 2.0 # 硬止损 = ATR × 2.0
TIME_STOP_BARS = 3 # 3根K线未盈利平仓
TRAIL_START_ATR = 1.0 # 盈利 1×ATR 后启动移动止损
TRAIL_ATR_MULT = 0.5 # 移动止损距离 0.5×ATR
# 止盈目标ATR倍数与分批比例
TP1_ATR = 1.5
TP2_ATR = 3.0
TP3_ATR = 5.0
TP1_RATIO = 0.30
TP2_RATIO = 0.30
TP3_RATIO = 0.40
# ========== 反手条件 ==========
REVERSE_BREAK_MULT = 0.5 # 突破幅度 > 实体/2
REVERSE_LOSS_ATR = 0.5 # 当前持仓亏损 > 0.5×ATR 可反手
MIN_BARS_SINCE_ENTRY = 2 # 距离上次开仓至少2根K线
SAME_KLINE_NO_REVERSE = True # 同一K线不反手
# ========== 市场状态调整 ==========
# 强趋势 / 震荡 / 高波动 时的系数
STRONG_TREND_COEF = 0.25
STRONG_TREND_STOP_ATR = 3.0
RANGE_COEF = 0.4
RANGE_STOP_ATR = 1.5
HIGH_VOL_POSITION_COEF = 0.5
HIGH_VOL_EXTRA_CONFIRM = 1
# ========== 禁止交易时段UTC+8 小时:分) ==========
FORBIDDEN_PERIODS = [
(0, 0, 0, 30), # 00:00-00:30
(8, 0, 8, 30), # 08:00-08:30
(20, 0, 20, 30), # 20:00-20:30
]
# 高波动暂停ATR > 平均ATR × 2 暂停
ATR_PAUSE_MULT = 2.0
# ========== 自适应绩效 ==========
CONSECUTIVE_LOSS_PAUSE = 3 # 连续亏损3次仓位减半
WIN_RATE_LOOKBACK = 20
WIN_RATE_PAUSE_THRESHOLD = 0.40 # 胜率<40% 暂停
MAX_DRAWDOWN_PERCENT = 0.10 # 最大回撤10% 观察期
MAX_TRADES_PER_DAY = 20
MAX_HOLD_BARS = 4 * 12 # 4小时 ≈ 4*12 根5分钟
# ========== 回测/实盘通用 ==========
CONTRACT_SIZE = 10000
SLIPPAGE_POINTS = 3
FEE_RATE = 0.0005
FEE_FIXED = 5
# 回测专用:固定手续费(合约多为按比例,可设为 0 观察策略本身)
FEE_FIXED_BACKTEST = 0
# 两笔开仓之间至少间隔 N 根 5 分钟 K 线,减少过度交易
MIN_BARS_BETWEEN_TRADES = 4

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,697 @@
id,open,high,low,close,volume
1735660800,3412.6,3416.0,3390.39,3408.23,102369440.0
1735664400,3408.23,3410.38,3329.45,3362.6,239948902.0
1735668000,3362.62,3372.14,3349.24,3360.3,87820990.0
1735671600,3360.3,3367.9,3342.85,3354.68,42695570.0
1735675200,3354.68,3364.47,3336.84,3346.12,54111736.0
1735678800,3345.76,3354.28,3331.51,3351.72,48624216.0
1735682400,3351.66,3351.66,3327.8,3338.94,44710804.0
1735686000,3338.94,3345.03,3327.22,3336.37,37042226.0
1735689600,3336.47,3364.49,3334.99,3362.89,57465298.0
1735693200,3362.89,3365.08,3341.6,3345.83,34711202.0
1735696800,3345.83,3368.02,3345.35,3361.81,34405766.0
1735700400,3361.81,3363.0,3350.22,3354.34,21508812.0
1735704000,3354.34,3355.78,3338.4,3340.12,45813072.0
1735707600,3340.04,3350.57,3339.13,3344.2,29504628.0
1735711200,3344.2,3347.33,3335.57,3345.65,26979022.0
1735714800,3345.65,3347.77,3338.32,3346.0,19122736.0
1735718400,3345.94,3348.0,3330.48,3335.57,39528308.0
1735722000,3335.57,3340.16,3313.08,3333.4,129899100.0
1735725600,3333.52,3337.99,3325.01,3325.99,32584622.0
1735729200,3325.99,3347.73,3322.8,3340.07,45465420.0
1735732800,3340.07,3351.21,3337.29,3346.01,39172620.0
1735736400,3346.01,3352.78,3331.45,3343.1,51120458.0
1735740000,3342.83,3358.89,3327.15,3345.0,82299724.0
1735743600,3345.06,3354.24,3332.01,3352.07,51286002.0
1735747200,3352.07,3356.14,3331.27,3337.72,49132440.0
1735750800,3337.72,3344.37,3322.56,3343.02,49046866.0
1735754400,3343.01,3351.47,3332.38,3347.81,36271786.0
1735758000,3347.81,3363.82,3338.02,3356.2,55282332.0
1735761600,3356.2,3361.76,3351.0,3359.39,38099614.0
1735765200,3359.28,3370.87,3352.49,3367.59,51552628.0
1735768800,3367.59,3373.97,3357.81,3360.65,43553722.0
1735772400,3360.65,3365.99,3352.07,3359.35,33197468.0
1735776000,3359.35,3399.41,3354.01,3389.27,123638482.0
1735779600,3389.27,3404.76,3377.72,3383.02,72528314.0
1735783200,3383.1,3397.9,3376.89,3397.89,35142436.0
1735786800,3397.89,3401.77,3386.57,3388.01,28707566.0
1735790400,3388.01,3427.38,3387.4,3417.81,124752266.0
1735794000,3417.82,3419.18,3404.4,3412.37,64463210.0
1735797600,3412.63,3415.73,3401.82,3410.19,37061074.0
1735801200,3410.19,3421.77,3408.6,3419.68,42976506.0
1735804800,3419.68,3442.8,3414.59,3437.98,81383320.0
1735808400,3437.13,3470.72,3433.94,3467.93,117165150.0
1735812000,3467.93,3476.09,3457.49,3468.61,95625752.0
1735815600,3468.61,3474.99,3457.1,3470.47,55981282.0
1735819200,3470.46,3480.37,3465.1,3479.77,71134738.0
1735822800,3479.89,3483.94,3459.45,3465.33,135921684.0
1735826400,3465.33,3509.87,3439.82,3494.61,298463722.0
1735830000,3494.61,3495.56,3455.45,3462.76,137324232.0
1735833600,3462.76,3488.75,3447.84,3468.71,102691858.0
1735837200,3468.7,3478.07,3429.2,3449.77,130762240.0
1735840800,3449.66,3464.67,3439.64,3464.16,96730060.0
1735844400,3464.16,3473.57,3458.11,3462.31,52010818.0
1735848000,3462.31,3474.61,3450.9,3452.17,41220990.0
1735851600,3452.29,3455.39,3442.18,3453.73,48633000.0
1735855200,3453.73,3453.75,3419.06,3440.0,62033228.0
1735858800,3439.91,3456.41,3437.0,3454.81,33740154.0
1735862400,3454.81,3466.23,3445.58,3448.8,49005198.0
1735866000,3448.8,3465.02,3442.11,3464.36,64836976.0
1735869600,3464.36,3476.32,3455.92,3456.74,51253786.0
1735873200,3456.64,3471.96,3455.04,3469.22,41861896.0
1735876800,3469.21,3470.11,3455.0,3457.65,33613294.0
1735880400,3457.85,3459.99,3443.71,3455.13,57285134.0
1735884000,3455.13,3460.9,3441.01,3441.9,36792172.0
1735887600,3441.9,3443.62,3431.19,3432.52,64944146.0
1735891200,3432.52,3441.96,3422.35,3429.01,71555590.0
1735894800,3429.01,3449.99,3428.0,3442.67,45692272.0
1735898400,3442.66,3451.63,3437.26,3444.82,34326568.0
1735902000,3444.82,3466.53,3444.82,3464.73,51124624.0
1735905600,3464.47,3475.49,3460.01,3462.58,57106556.0
1735909200,3462.53,3496.26,3462.05,3480.31,136074052.0
1735912800,3480.36,3535.47,3479.85,3525.73,252612796.0
1735916400,3527.99,3575.99,3518.91,3564.31,266749252.0
1735920000,3564.31,3598.54,3564.2,3583.68,236728242.0
1735923600,3583.76,3593.0,3572.94,3574.28,77062022.0
1735927200,3574.28,3616.82,3573.18,3604.62,145063892.0
1735930800,3604.53,3629.68,3601.44,3621.89,136264822.0
1735934400,3621.89,3622.32,3599.55,3600.11,82316038.0
1735938000,3600.2,3615.64,3594.35,3613.51,60389536.0
1735941600,3613.51,3623.2,3609.21,3615.11,41030186.0
1735945200,3615.11,3616.87,3603.44,3607.89,55205762.0
1735948800,3607.89,3619.9,3601.06,3601.96,52305142.0
1735952400,3601.96,3603.52,3581.77,3595.65,60263730.0
1735956000,3595.65,3599.45,3582.0,3595.42,35032408.0
1735959600,3595.42,3599.48,3590.01,3597.04,28343560.0
1735963200,3597.08,3597.18,3583.1,3590.9,31587898.0
1735966800,3590.9,3596.15,3585.87,3595.52,27817296.0
1735970400,3595.52,3606.6,3594.06,3599.16,34022310.0
1735974000,3599.16,3609.0,3591.89,3593.04,43060454.0
1735977600,3593.04,3603.11,3584.0,3584.17,82921978.0
1735981200,3584.06,3594.99,3582.48,3588.57,39073846.0
1735984800,3588.57,3591.98,3570.92,3587.1,48068340.0
1735988400,3587.1,3605.05,3583.83,3601.16,55657250.0
1735992000,3601.16,3644.09,3599.35,3634.42,152503238.0
1735995600,3634.42,3648.59,3626.28,3643.77,105667482.0
1735999200,3643.77,3646.0,3631.36,3636.4,63779260.0
1736002800,3636.4,3662.37,3592.27,3606.5,238821272.0
1736006400,3606.5,3627.64,3600.3,3620.72,76957118.0
1736010000,3620.89,3633.52,3618.89,3632.52,40292730.0
1736013600,3632.52,3643.7,3618.0,3625.99,47967500.0
1736017200,3625.99,3638.39,3623.02,3629.81,24410624.0
1736020800,3629.81,3667.58,3629.81,3659.31,70469288.0
1736024400,3659.31,3669.95,3653.82,3657.57,60929522.0
1736028000,3657.57,3662.13,3645.68,3658.81,34926154.0
1736031600,3658.81,3664.88,3649.92,3655.98,35246640.0
1736035200,3655.98,3674.56,3646.87,3648.66,55777438.0
1736038800,3648.66,3650.3,3630.11,3635.55,52527572.0
1736042400,3635.55,3644.01,3633.69,3640.11,24195566.0
1736046000,3640.11,3640.9,3628.03,3636.5,20439542.0
1736049600,3636.5,3648.0,3635.87,3642.88,29199868.0
1736053200,3642.88,3642.9,3629.28,3631.5,26183660.0
1736056800,3631.5,3640.66,3626.93,3637.54,20101968.0
1736060400,3637.54,3640.13,3628.97,3630.38,19147964.0
1736064000,3630.38,3632.11,3607.51,3618.97,102512590.0
1736067600,3618.97,3622.41,3604.01,3608.53,47549468.0
1736071200,3608.65,3617.6,3601.63,3614.68,40940760.0
1736074800,3614.68,3620.13,3608.33,3612.57,30546036.0
1736078400,3612.57,3621.77,3603.95,3612.88,43155640.0
1736082000,3613.04,3626.65,3611.35,3613.49,37524524.0
1736085600,3613.49,3627.36,3592.53,3621.73,135663724.0
1736089200,3621.65,3637.67,3618.01,3628.43,75103806.0
1736092800,3628.43,3640.01,3623.01,3627.1,60533890.0
1736096400,3627.1,3647.35,3621.0,3627.36,52375452.0
1736100000,3627.14,3632.37,3611.43,3629.47,43996958.0
1736103600,3629.47,3638.96,3625.0,3636.9,25938496.0
1736107200,3636.9,3657.0,3627.34,3634.52,61275846.0
1736110800,3634.52,3647.21,3632.96,3644.52,23260872.0
1736114400,3644.52,3648.89,3633.14,3644.18,23637400.0
1736118000,3644.15,3654.47,3631.56,3634.85,35985516.0
1736121600,3634.85,3654.52,3620.5,3620.5,61317924.0
1736125200,3620.67,3654.84,3608.95,3647.81,86153808.0
1736128800,3647.51,3684.08,3644.14,3657.59,182952938.0
1736132400,3657.5,3673.87,3652.98,3663.93,46604218.0
1736136000,3663.93,3678.2,3659.69,3671.82,46449432.0
1736139600,3671.82,3697.99,3666.17,3679.61,99035916.0
1736143200,3679.61,3684.04,3664.12,3664.87,52617428.0
1736146800,3664.87,3667.1,3641.26,3649.39,93646214.0
1736150400,3649.39,3659.4,3635.02,3639.98,82925846.0
1736154000,3639.98,3649.36,3639.06,3643.89,28971374.0
1736157600,3643.89,3645.87,3631.43,3637.07,42695740.0
1736161200,3637.07,3658.44,3635.1,3653.7,56217424.0
1736164800,3653.7,3661.82,3640.68,3641.68,59441302.0
1736168400,3641.68,3651.94,3623.81,3650.0,96201734.0
1736172000,3650.0,3702.32,3621.12,3684.3,289303830.0
1736175600,3684.26,3713.01,3670.27,3711.59,260080200.0
1736179200,3712.89,3743.7,3690.41,3709.39,272849142.0
1736182800,3709.39,3710.16,3654.92,3672.78,176868982.0
1736186400,3672.78,3691.03,3661.17,3681.2,68879960.0
1736190000,3681.31,3694.94,3674.38,3686.47,39532406.0
1736193600,3686.47,3702.68,3671.65,3682.33,59308086.0
1736197200,3682.07,3687.78,3665.39,3666.31,51081846.0
1736200800,3666.31,3682.56,3666.1,3677.43,38055272.0
1736204400,3677.43,3686.36,3667.4,3685.72,28287998.0
1736208000,3685.72,3693.4,3672.22,3674.01,48983234.0
1736211600,3674.01,3695.78,3661.96,3693.68,48454388.0
1736215200,3693.68,3699.99,3675.01,3676.88,41902274.0
1736218800,3676.87,3687.99,3672.81,3681.48,34679266.0
1736222400,3681.48,3685.53,3672.38,3672.4,22079898.0
1736226000,3672.4,3676.15,3657.64,3668.64,45811008.0
1736229600,3668.64,3674.79,3663.01,3671.53,29019498.0
1736233200,3671.53,3678.99,3661.35,3666.6,29153142.0
1736236800,3666.6,3678.49,3659.26,3673.4,41854680.0
1736240400,3673.4,3675.58,3652.21,3660.13,57671204.0
1736244000,3660.14,3665.0,3650.39,3657.01,42289288.0
1736247600,3657.01,3657.99,3625.07,3638.34,132520824.0
1736251200,3638.6,3642.32,3625.51,3632.68,67571326.0
1736254800,3632.68,3644.9,3630.15,3635.14,48976982.0
1736258400,3635.2,3641.18,3523.0,3567.07,333440168.0
1736262000,3567.07,3580.49,3410.38,3461.46,1085438710.0
1736265600,3461.33,3490.42,3447.53,3456.8,250533314.0
1736269200,3456.8,3469.33,3420.12,3441.09,227652302.0
1736272800,3440.99,3458.14,3411.8,3420.51,182306610.0
1736276400,3420.51,3436.46,3374.36,3384.93,267051616.0
1736280000,3384.59,3399.26,3362.16,3395.32,175652002.0
1736283600,3395.27,3412.8,3359.81,3361.96,139760754.0
1736287200,3362.09,3396.25,3355.13,3395.21,96223134.0
1736290800,3395.21,3395.21,3373.61,3379.37,51490032.0
1736294400,3379.37,3413.55,3376.91,3410.01,87357960.0
1736298000,3410.09,3410.12,3373.39,3389.82,70746830.0
1736301600,3389.82,3402.98,3381.2,3381.23,51129254.0
1736305200,3381.23,3386.39,3342.71,3359.34,186577674.0
1736308800,3359.34,3372.73,3342.07,3347.27,105866768.0
1736312400,3347.27,3371.89,3336.08,3350.48,104936154.0
1736316000,3350.48,3361.34,3306.03,3307.77,211327564.0
1736319600,3307.8,3358.07,3306.71,3353.19,146187366.0
1736323200,3353.19,3375.59,3349.83,3364.56,101254772.0
1736326800,3364.57,3372.85,3345.0,3345.89,75539896.0
1736330400,3345.89,3371.99,3345.16,3360.9,69829694.0
1736334000,3360.9,3366.39,3321.76,3348.44,164453210.0
1736337600,3348.44,3359.3,3337.6,3338.59,85930986.0
1736341200,3338.61,3365.29,3338.61,3357.39,89649230.0
1736344800,3357.21,3380.52,3346.3,3369.27,151342344.0
1736348400,3368.94,3384.66,3332.0,3345.99,206886030.0
1736352000,3345.99,3347.06,3310.44,3313.07,148369138.0
1736355600,3313.11,3318.93,3207.46,3262.23,658990620.0
1736359200,3262.21,3329.38,3257.5,3281.58,286190748.0
1736362800,3281.99,3308.69,3270.47,3279.62,140264688.0
1736366400,3279.57,3290.0,3265.01,3284.51,65621974.0
1736370000,3284.51,3303.67,3268.87,3297.9,74963226.0
1736373600,3297.85,3332.86,3297.28,3331.31,80470748.0
1736377200,3331.31,3333.47,3314.73,3325.46,41780554.0
1736380800,3325.46,3342.07,3316.67,3340.7,60166482.0
1736384400,3340.12,3356.49,3333.9,3344.64,63614256.0
1736388000,3344.64,3349.59,3305.94,3339.6,165240584.0
1736391600,3339.6,3341.35,3315.56,3324.06,63469448.0
1736395200,3323.71,3342.24,3311.0,3339.0,67512222.0
1736398800,3338.96,3341.19,3323.42,3327.38,39150924.0
1736402400,3327.38,3333.77,3313.68,3314.92,41707280.0
1736406000,3314.92,3323.33,3281.3,3288.19,154505570.0
1736409600,3288.19,3325.89,3263.38,3308.99,192210656.0
1736413200,3309.07,3326.72,3305.94,3316.68,65498146.0
1736416800,3316.68,3321.07,3283.42,3310.84,106064710.0
1736420400,3310.84,3325.5,3292.07,3300.36,76143062.0
1736424000,3300.36,3309.23,3279.89,3294.89,72951552.0
1736427600,3294.89,3297.76,3211.02,3219.8,310900906.0
1736431200,3219.6,3251.76,3209.02,3249.62,207212678.0
1736434800,3249.62,3335.0,3242.45,3318.81,240337982.0
1736438400,3318.81,3326.2,3286.7,3300.79,164041718.0
1736442000,3300.79,3302.94,3234.38,3249.49,184871012.0
1736445600,3249.49,3269.11,3244.47,3258.78,103697430.0
1736449200,3259.07,3267.62,3190.01,3193.56,229460404.0
1736452800,3193.54,3212.74,3155.96,3194.13,302442148.0
1736456400,3194.12,3224.91,3189.44,3206.78,90139568.0
1736460000,3205.89,3238.13,3186.39,3222.7,89771046.0
1736463600,3222.7,3231.72,3208.6,3217.86,49759112.0
1736467200,3218.13,3232.61,3212.86,3221.74,54670720.0
1736470800,3221.74,3238.89,3212.52,3235.53,61826016.0
1736474400,3235.53,3258.78,3229.27,3239.91,73960624.0
1736478000,3240.12,3254.85,3237.3,3253.05,39189052.0
1736481600,3253.05,3263.57,3245.37,3252.64,52641914.0
1736485200,3252.78,3280.15,3241.27,3262.78,81991616.0
1736488800,3262.6,3279.35,3258.56,3276.45,46459632.0
1736492400,3276.45,3312.38,3269.49,3294.65,142743074.0
1736496000,3294.65,3300.61,3286.36,3294.77,54960336.0
1736499600,3294.77,3309.3,3289.02,3301.2,55245834.0
1736503200,3301.2,3319.92,3296.47,3316.89,63228784.0
1736506800,3316.89,3318.66,3294.49,3309.74,69342416.0
1736510400,3309.74,3311.0,3291.98,3309.36,67812524.0
1736514000,3309.25,3315.95,3215.36,3242.94,442746528.0
1736517600,3242.94,3277.64,3235.03,3255.47,229753402.0
1736521200,3253.81,3274.86,3193.21,3243.69,363287258.0
1736524800,3243.54,3260.64,3231.0,3246.19,141134442.0
1736528400,3246.11,3320.22,3241.43,3313.36,173307620.0
1736532000,3313.27,3313.27,3280.14,3285.21,117654418.0
1736535600,3285.76,3297.7,3269.11,3293.79,84001780.0
1736539200,3293.79,3293.8,3256.27,3258.81,62458836.0
1736542800,3258.71,3273.33,3256.01,3264.13,32978326.0
1736546400,3264.13,3280.1,3258.48,3272.36,35630396.0
1736550000,3272.36,3274.17,3263.04,3265.52,22914060.0
1736553600,3265.52,3268.92,3256.51,3264.4,38075382.0
1736557200,3264.4,3266.68,3235.13,3244.52,61301216.0
1736560800,3244.52,3250.87,3236.17,3246.5,29747936.0
1736564400,3246.5,3247.11,3230.52,3235.88,28924308.0
1736568000,3235.88,3242.0,3228.51,3237.53,32303354.0
1736571600,3237.53,3244.92,3231.48,3244.35,33205960.0
1736575200,3244.35,3249.5,3236.31,3236.33,28510900.0
1736578800,3236.33,3243.13,3224.17,3234.72,38537850.0
1736582400,3234.72,3239.07,3215.12,3223.37,48376530.0
1736586000,3223.37,3243.45,3222.27,3243.01,49518806.0
1736589600,3243.01,3255.31,3242.22,3255.26,79756560.0
1736593200,3255.26,3279.23,3252.9,3272.68,95103116.0
1736596800,3272.68,3280.0,3266.71,3271.65,39652500.0
1736600400,3271.65,3274.82,3257.51,3266.4,49449588.0
1736604000,3266.4,3278.98,3257.26,3277.3,42866688.0
1736607600,3277.2,3281.01,3265.16,3270.07,31206676.0
1736611200,3270.07,3277.14,3261.0,3274.11,31282780.0
1736614800,3274.11,3274.9,3257.7,3270.89,40054362.0
1736618400,3270.89,3279.01,3266.11,3277.06,18851470.0
1736622000,3276.96,3282.49,3268.28,3277.47,31217294.0
1736625600,3277.47,3299.48,3274.61,3298.28,40594708.0
1736629200,3298.28,3319.01,3298.05,3305.69,62717802.0
1736632800,3305.69,3307.36,3284.5,3287.56,40714280.0
1736636400,3287.56,3293.32,3280.33,3281.85,29895820.0
1736640000,3281.85,3286.11,3277.98,3282.18,22834780.0
1736643600,3282.18,3288.32,3273.02,3287.87,25636570.0
1736647200,3287.87,3288.96,3278.26,3288.87,17973236.0
1736650800,3288.87,3289.88,3277.02,3285.27,19745114.0
1736654400,3285.27,3288.62,3279.52,3282.52,17536690.0
1736658000,3282.52,3284.4,3273.11,3278.51,18182922.0
1736661600,3278.51,3280.29,3266.38,3269.24,28730928.0
1736665200,3269.24,3272.82,3262.31,3265.63,38470516.0
1736668800,3265.62,3270.61,3233.02,3238.36,122652126.0
1736672400,3238.45,3243.5,3223.13,3236.97,107510624.0
1736676000,3236.97,3244.82,3232.45,3243.12,47696088.0
1736679600,3243.12,3257.11,3239.67,3251.63,50138698.0
1736683200,3251.86,3264.27,3246.51,3249.24,57619188.0
1736686800,3249.24,3270.58,3246.94,3266.0,68944450.0
1736690400,3266.0,3279.9,3265.0,3267.83,73240184.0
1736694000,3267.83,3294.5,3264.0,3284.65,79888684.0
1736697600,3284.65,3286.99,3267.61,3280.51,43169660.0
1736701200,3280.51,3291.46,3277.19,3287.9,46143554.0
1736704800,3287.81,3298.89,3279.33,3283.73,47041518.0
1736708400,3283.73,3287.97,3274.66,3279.11,25800656.0
1736712000,3279.11,3288.49,3272.07,3280.55,23003516.0
1736715600,3280.63,3281.94,3262.59,3265.11,44126248.0
1736719200,3265.12,3267.41,3232.85,3239.17,101407078.0
1736722800,3239.17,3267.36,3237.68,3265.69,44761358.0
1736726400,3265.69,3338.19,3263.9,3307.67,252955806.0
1736730000,3307.43,3311.66,3251.27,3260.13,196644388.0
1736733600,3260.13,3269.95,3236.0,3254.9,121374346.0
1736737200,3254.9,3265.89,3234.02,3241.24,90367330.0
1736740800,3241.24,3259.58,3236.46,3237.36,78938608.0
1736744400,3237.36,3237.8,3211.68,3224.18,119089336.0
1736748000,3224.49,3232.3,3180.01,3190.13,176832932.0
1736751600,3190.1,3208.74,3181.93,3200.53,86710800.0
1736755200,3200.53,3205.45,3159.9,3168.74,156073064.0
1736758800,3168.74,3176.15,3119.18,3155.01,234976700.0
1736762400,3155.01,3155.99,3106.07,3117.96,317611886.0
1736766000,3118.75,3123.04,3055.09,3056.7,378759676.0
1736769600,3056.4,3084.95,3039.54,3045.72,305548852.0
1736773200,3045.89,3090.3,3032.3,3059.44,249979524.0
1736776800,3059.44,3060.11,2909.6,3033.47,974243346.0
1736780400,3033.59,3076.35,3025.13,3047.42,366822882.0
1736784000,3047.42,3058.66,3004.86,3008.65,234479378.0
1736787600,3007.87,3035.84,3003.01,3019.36,152995168.0
1736791200,3019.36,3032.98,2985.02,3006.39,179997976.0
1736794800,3006.38,3036.47,2991.8,3023.97,125369102.0
1736798400,3023.97,3103.38,3010.35,3090.15,177752432.0
1736802000,3090.41,3118.78,3081.97,3112.72,165786786.0
1736805600,3112.72,3141.66,3110.97,3130.64,116974672.0
1736809200,3130.64,3139.43,3124.38,3136.15,47544220.0
1736812800,3136.15,3147.25,3124.06,3132.57,84185166.0
1736816400,3132.57,3157.97,3132.19,3138.01,94074596.0
1736820000,3137.9,3165.79,3130.36,3155.98,85221592.0
1736823600,3155.98,3174.3,3153.45,3157.58,54405210.0
1736827200,3157.58,3174.12,3157.58,3171.39,55857890.0
1736830800,3171.23,3181.33,3158.29,3160.65,79933988.0
1736834400,3160.65,3187.06,3156.26,3182.95,73104704.0
1736838000,3182.95,3189.0,3169.86,3170.4,56505048.0
1736841600,3170.4,3191.27,3168.36,3181.91,74257186.0
1736845200,3182.0,3255.21,3176.59,3242.42,259501370.0
1736848800,3242.42,3242.89,3219.7,3233.75,124964948.0
1736852400,3233.75,3234.23,3209.7,3216.28,67811012.0
1736856000,3216.12,3218.73,3179.51,3182.39,163014218.0
1736859600,3182.5,3231.74,3178.0,3207.21,199494486.0
1736863200,3207.22,3232.31,3186.1,3190.41,130742936.0
1736866800,3190.94,3214.98,3186.11,3197.86,137337984.0
1736870400,3197.86,3202.94,3171.03,3189.99,137636112.0
1736874000,3189.99,3211.7,3182.72,3211.33,80978048.0
1736877600,3211.1,3231.4,3205.89,3223.37,92417500.0
1736881200,3223.37,3234.31,3211.09,3212.9,62213378.0
1736884800,3212.9,3224.69,3193.52,3221.24,82723252.0
1736888400,3221.24,3232.5,3211.25,3214.72,50505536.0
1736892000,3214.72,3239.2,3212.11,3233.81,35697584.0
1736895600,3233.81,3236.6,3221.18,3223.99,28458870.0
1736899200,3223.99,3241.26,3216.09,3220.18,62474718.0
1736902800,3220.18,3244.58,3215.73,3228.96,71656158.0
1736906400,3228.96,3238.69,3205.0,3211.66,70425488.0
1736910000,3211.77,3240.66,3207.26,3239.89,54759212.0
1736913600,3239.88,3251.11,3220.79,3225.01,81473270.0
1736917200,3224.99,3234.39,3213.86,3228.57,46760866.0
1736920800,3228.57,3231.82,3215.17,3229.14,47369732.0
1736924400,3229.14,3249.69,3228.61,3231.31,72666604.0
1736928000,3231.31,3246.86,3228.52,3230.98,60786620.0
1736931600,3231.1,3236.52,3195.34,3199.21,97527064.0
1736935200,3199.21,3217.14,3196.79,3208.08,62126134.0
1736938800,3208.08,3208.96,3185.53,3198.3,77459828.0
1736942400,3198.3,3210.72,3185.4,3200.66,78921674.0
1736946000,3200.66,3297.25,3200.4,3297.01,361680060.0
1736949600,3297.01,3330.61,3274.57,3328.32,260514000.0
1736953200,3328.37,3353.09,3324.53,3333.17,216457060.0
1736956800,3333.07,3365.41,3332.56,3338.3,139245078.0
1736960400,3338.3,3357.46,3322.99,3324.68,90410118.0
1736964000,3324.68,3373.77,3324.68,3370.89,81676352.0
1736967600,3370.8,3442.18,3366.66,3433.76,263310966.0
1736971200,3433.76,3472.38,3431.66,3432.83,208944138.0
1736974800,3432.81,3445.86,3426.0,3431.39,62340338.0
1736978400,3431.39,3434.99,3417.53,3429.39,51207524.0
1736982000,3429.48,3451.12,3419.23,3449.82,66010384.0
1736985600,3449.82,3458.48,3385.69,3397.95,171382692.0
1736989200,3397.95,3412.55,3391.65,3402.58,46722624.0
1736992800,3402.58,3405.0,3380.39,3384.03,61431958.0
1736996400,3384.03,3386.8,3345.74,3362.11,132369822.0
1737000000,3362.11,3374.53,3360.45,3373.24,55905782.0
1737003600,3373.24,3376.07,3364.58,3366.9,27209092.0
1737007200,3366.9,3386.02,3361.78,3378.89,55504360.0
1737010800,3378.86,3389.29,3375.89,3382.41,42026166.0
1737014400,3382.41,3384.0,3301.88,3315.42,213550818.0
1737018000,3315.44,3335.0,3298.01,3334.8,173270654.0
1737021600,3334.8,3340.99,3328.0,3332.2,59671834.0
1737025200,3332.87,3354.87,3320.07,3349.64,111186100.0
1737028800,3349.65,3363.28,3340.11,3355.43,97407238.0
1737032400,3355.53,3357.3,3309.0,3327.07,167514778.0
1737036000,3327.1,3341.53,3264.28,3276.1,285205966.0
1737039600,3276.25,3332.09,3268.53,3331.98,228397622.0
1737043200,3331.98,3360.66,3329.4,3339.22,152861984.0
1737046800,3338.77,3364.41,3329.91,3342.69,93468544.0
1737050400,3342.69,3349.79,3308.93,3324.61,90234800.0
1737054000,3324.61,3344.94,3318.01,3343.35,43458370.0
1737057600,3343.35,3351.99,3324.68,3335.77,53289036.0
1737061200,3335.71,3336.78,3310.16,3319.09,54644580.0
1737064800,3319.09,3319.31,3267.03,3296.7,131717852.0
1737068400,3296.7,3311.39,3289.02,3306.93,68247846.0
1737072000,3306.93,3316.78,3306.59,3312.78,42675412.0
1737075600,3312.78,3393.76,3312.72,3384.73,214952370.0
1737079200,3384.73,3396.23,3354.05,3372.07,140006948.0
1737082800,3372.07,3376.06,3357.4,3359.98,47167210.0
1737086400,3359.98,3371.42,3346.44,3369.69,64118896.0
1737090000,3369.69,3374.77,3358.19,3365.51,44641394.0
1737093600,3365.51,3374.7,3363.39,3366.38,39763556.0
1737097200,3366.38,3393.91,3361.3,3371.36,70940042.0
1737100800,3371.36,3412.78,3371.0,3405.9,121892422.0
1737104400,3405.9,3413.03,3399.07,3402.51,70929662.0
1737108000,3402.51,3437.78,3401.1,3426.64,102788236.0
1737111600,3426.64,3429.5,3415.53,3422.1,55018198.0
1737115200,3422.1,3425.46,3399.89,3406.78,90512196.0
1737118800,3406.78,3422.93,3394.96,3400.81,77679768.0
1737122400,3400.76,3431.89,3400.75,3427.7,167275558.0
1737126000,3427.49,3449.69,3403.1,3420.33,195084666.0
1737129600,3420.32,3447.59,3410.53,3436.43,111256436.0
1737133200,3436.43,3441.9,3406.02,3413.26,100510326.0
1737136800,3413.38,3428.83,3409.07,3410.49,47213594.0
1737140400,3410.49,3443.03,3409.73,3430.79,91962986.0
1737144000,3431.02,3524.4,3424.26,3514.04,286751750.0
1737147600,3514.04,3524.53,3465.44,3472.64,136440486.0
1737151200,3472.64,3486.56,3466.01,3468.91,61781218.0
1737154800,3468.91,3483.87,3461.49,3472.39,47196678.0
1737158400,3472.39,3492.94,3467.34,3485.83,52615116.0
1737162000,3485.83,3485.83,3453.85,3464.95,63843980.0
1737165600,3464.95,3473.28,3446.9,3450.06,47257378.0
1737169200,3450.11,3455.0,3366.79,3382.77,229697520.0
1737172800,3382.77,3394.52,3350.01,3364.52,172058940.0
1737176400,3364.52,3369.99,3290.01,3292.89,274237194.0
1737180000,3292.89,3339.39,3291.66,3312.76,153000770.0
1737183600,3312.76,3314.37,3280.01,3286.46,147604794.0
1737187200,3286.47,3294.66,3251.0,3291.85,228254978.0
1737190800,3291.85,3299.87,3252.31,3269.83,127768426.0
1737194400,3269.89,3276.99,3225.14,3265.78,252550352.0
1737198000,3265.81,3323.48,3247.76,3310.18,227271112.0
1737201600,3310.29,3320.91,3273.3,3288.68,159370596.0
1737205200,3288.68,3322.36,3278.33,3321.84,137949644.0
1737208800,3321.84,3325.22,3287.76,3295.86,97189442.0
1737212400,3295.86,3346.2,3283.95,3305.77,219267024.0
1737216000,3305.89,3315.72,3252.51,3252.51,243473644.0
1737219600,3252.51,3284.8,3252.12,3257.2,97599068.0
1737223200,3256.5,3283.03,3249.0,3263.66,83528110.0
1737226800,3263.54,3292.49,3260.39,3289.08,56544316.0
1737230400,3289.08,3290.88,3256.74,3264.87,58021088.0
1737234000,3264.88,3285.06,3262.08,3273.72,37319280.0
1737237600,3273.72,3287.67,3270.02,3279.36,30291248.0
1737241200,3279.42,3320.34,3278.22,3306.69,83215168.0
1737244800,3306.69,3322.38,3297.72,3315.68,66796494.0
1737248400,3315.68,3365.18,3312.9,3352.57,155449194.0
1737252000,3352.57,3377.32,3346.9,3352.47,82240816.0
1737255600,3352.47,3365.32,3332.52,3334.97,97009222.0
1737259200,3334.97,3337.32,3276.02,3282.51,202282652.0
1737262800,3282.51,3299.78,3258.18,3298.57,105321972.0
1737266400,3298.57,3299.93,3280.91,3282.12,47257870.0
1737270000,3282.18,3292.37,3261.31,3275.02,88322326.0
1737273600,3275.02,3277.15,3215.0,3221.19,203332442.0
1737277200,3221.19,3233.18,3143.11,3226.34,411242284.0
1737280800,3225.66,3226.18,3173.02,3174.2,166786984.0
1737284400,3174.3,3188.53,3131.0,3149.56,209689408.0
1737288000,3150.33,3210.59,3144.26,3205.26,164299906.0
1737291600,3205.26,3277.31,3193.14,3273.7,251270350.0
1737295200,3275.24,3395.99,3258.42,3380.19,863763538.0
1737298800,3380.11,3424.81,3352.82,3383.79,333831610.0
1737302400,3383.77,3424.04,3377.57,3410.83,168812328.0
1737306000,3410.88,3448.14,3385.96,3442.35,194255198.0
1737309600,3442.35,3449.0,3406.9,3434.0,106325700.0
1737313200,3433.4,3434.0,3407.59,3419.94,57312166.0
1737316800,3419.94,3432.95,3351.04,3378.22,144020792.0
1737320400,3378.22,3379.4,3207.05,3235.01,501866746.0
1737324000,3232.5,3311.84,3156.18,3265.77,478996130.0
1737327600,3265.76,3265.76,3160.07,3213.52,466762210.0
1737331200,3214.05,3225.31,3142.73,3170.28,407986910.0
1737334800,3170.27,3219.48,3165.19,3200.27,229060286.0
1737338400,3199.96,3273.76,3196.01,3243.54,218587436.0
1737342000,3244.04,3279.99,3227.01,3271.39,119161842.0
1737345600,3271.35,3298.81,3249.6,3269.87,100450292.0
1737349200,3269.87,3318.14,3266.79,3290.91,124554022.0
1737352800,3290.91,3454.72,3285.41,3417.53,388228564.0
1737356400,3417.41,3441.9,3351.89,3383.02,374577926.0
1737360000,3382.95,3412.04,3380.02,3392.15,127096766.0
1737363600,3392.15,3411.93,3352.99,3364.15,186871672.0
1737367200,3364.15,3391.99,3341.78,3354.39,126612530.0
1737370800,3354.39,3388.33,3334.21,3375.69,172373108.0
1737374400,3375.69,3379.6,3256.4,3303.82,367009686.0
1737378000,3303.93,3354.87,3295.01,3342.28,210560350.0
1737381600,3342.23,3361.6,3329.61,3358.56,154930784.0
1737385200,3358.55,3378.98,3315.21,3335.57,241523322.0
1737388800,3335.93,3390.0,3276.81,3380.16,274158310.0
1737392400,3379.9,3384.07,3205.0,3292.24,795072372.0
1737396000,3292.24,3341.58,3283.72,3330.16,213855650.0
1737399600,3330.04,3364.11,3308.4,3342.92,128630890.0
1737403200,3342.92,3344.32,3313.98,3320.27,77237838.0
1737406800,3320.27,3337.16,3280.51,3284.42,82249858.0
1737410400,3284.36,3324.16,3255.28,3318.25,103096784.0
1737414000,3318.14,3320.28,3260.59,3283.21,98151492.0
1737417600,3283.21,3289.47,3220.47,3225.66,167574272.0
1737421200,3225.9,3260.77,3203.89,3250.4,181075574.0
1737424800,3250.4,3272.75,3227.81,3256.73,97124780.0
1737428400,3256.73,3269.67,3248.01,3262.23,63734320.0
1737432000,3262.23,3262.25,3212.81,3246.37,95284392.0
1737435600,3246.37,3253.9,3216.03,3224.39,73892594.0
1737439200,3224.65,3253.97,3212.82,3241.15,98098922.0
1737442800,3241.15,3266.0,3234.55,3254.01,67830494.0
1737446400,3254.0,3262.97,3233.55,3253.27,67584610.0
1737450000,3253.27,3276.4,3249.82,3275.74,77660896.0
1737453600,3275.74,3308.8,3270.41,3302.06,104765974.0
1737457200,3302.06,3313.19,3291.81,3304.39,91283102.0
1737460800,3304.39,3325.85,3293.07,3306.62,128372258.0
1737464400,3306.62,3314.49,3288.96,3308.85,80976134.0
1737468000,3308.71,3333.73,3279.0,3288.51,211256600.0
1737471600,3288.51,3300.99,3261.77,3294.1,128559286.0
1737475200,3294.1,3349.14,3289.36,3313.34,197211854.0
1737478800,3313.15,3356.04,3307.09,3350.37,90531198.0
1737482400,3350.37,3367.88,3329.87,3345.17,100399176.0
1737486000,3345.18,3346.29,3317.24,3331.74,80784936.0
1737489600,3331.74,3339.63,3303.34,3313.41,70082146.0
1737493200,3313.43,3335.71,3301.87,3331.61,54339844.0
1737496800,3331.58,3346.58,3326.0,3333.06,38895058.0
1737500400,3333.91,3334.32,3307.27,3326.74,73269766.0
1737504000,3326.74,3365.96,3322.53,3361.54,73640766.0
1737507600,3361.54,3361.83,3321.61,3328.53,68953758.0
1737511200,3328.34,3346.78,3322.0,3343.32,51151860.0
1737514800,3343.32,3347.85,3327.2,3330.54,33271698.0
1737518400,3330.54,3332.93,3315.84,3331.15,33810516.0
1737522000,3331.15,3339.33,3317.01,3317.66,29934040.0
1737525600,3317.66,3323.48,3301.61,3308.82,50870486.0
1737529200,3308.82,3310.36,3286.18,3287.05,76036546.0
1737532800,3286.97,3300.02,3273.0,3298.39,92349262.0
1737536400,3298.39,3303.49,3289.1,3297.4,35948534.0
1737540000,3297.4,3307.4,3287.82,3306.99,40550278.0
1737543600,3306.99,3328.83,3303.3,3325.53,53272540.0
1737547200,3325.53,3331.45,3310.14,3315.9,52994384.0
1737550800,3315.85,3318.31,3279.25,3283.32,100473366.0
1737554400,3283.39,3310.99,3266.7,3292.02,165657884.0
1737558000,3292.72,3304.69,3268.95,3277.5,108866836.0
1737561600,3277.5,3282.91,3261.0,3277.1,97706330.0
1737565200,3277.15,3287.01,3271.02,3284.6,48476310.0
1737568800,3284.6,3290.85,3239.08,3248.93,96991712.0
1737572400,3249.38,3279.0,3247.52,3261.51,73598538.0
1737576000,3261.51,3276.21,3253.01,3255.86,46359000.0
1737579600,3255.82,3264.32,3240.0,3258.42,64803018.0
1737583200,3258.42,3265.69,3231.89,3237.63,52779412.0
1737586800,3237.63,3245.99,3221.53,3241.77,78166668.0
1737590400,3241.77,3260.81,3237.04,3252.92,56714310.0
1737594000,3252.92,3257.59,3220.0,3234.28,65753656.0
1737597600,3234.34,3236.57,3203.23,3222.26,94598842.0
1737601200,3222.48,3242.35,3214.38,3225.64,57395280.0
1737604800,3225.71,3230.89,3182.66,3196.01,114327136.0
1737608400,3196.01,3220.5,3195.34,3213.89,55114374.0
1737612000,3213.89,3223.98,3203.26,3207.1,39191160.0
1737615600,3207.1,3232.44,3197.39,3231.96,53561668.0
1737619200,3231.96,3232.44,3207.44,3209.22,45550378.0
1737622800,3209.26,3221.14,3191.13,3195.94,60758744.0
1737626400,3195.94,3212.68,3187.34,3203.3,65237070.0
1737630000,3203.3,3216.15,3194.82,3212.78,49857888.0
1737633600,3212.78,3217.94,3188.52,3202.62,78595334.0
1737637200,3202.62,3242.4,3201.12,3233.01,108985424.0
1737640800,3232.89,3285.36,3221.81,3274.6,249651856.0
1737644400,3274.6,3280.91,3225.01,3258.51,281277612.0
1737648000,3258.51,3296.73,3252.0,3253.65,190993782.0
1737651600,3253.64,3270.76,3230.02,3264.89,108032146.0
1737655200,3264.92,3269.43,3234.0,3239.9,70643910.0
1737658800,3239.9,3245.0,3193.09,3203.76,157291960.0
1737662400,3203.71,3294.1,3195.86,3246.15,442292904.0
1737666000,3246.11,3255.52,3212.77,3247.4,120420326.0
1737669600,3247.85,3322.98,3245.19,3321.94,160218202.0
1737673200,3321.66,3347.53,3311.27,3337.88,118336168.0
1737676800,3337.88,3348.99,3284.11,3284.72,117342552.0
1737680400,3284.69,3325.37,3283.51,3297.47,90561650.0
1737684000,3297.49,3313.1,3278.58,3284.64,67232158.0
1737687600,3285.21,3311.93,3275.0,3301.41,91279686.0
1737691200,3301.35,3339.92,3291.13,3332.72,87852684.0
1737694800,3332.45,3409.47,3328.55,3409.22,199536164.0
1737698400,3409.28,3420.61,3378.01,3385.27,167874148.0
1737702000,3385.32,3400.36,3371.39,3380.59,82619272.0
1737705600,3380.59,3415.57,3374.6,3400.57,104233816.0
1737709200,3400.58,3412.03,3391.01,3400.87,62308630.0
1737712800,3400.73,3414.21,3390.53,3412.88,57566642.0
1737716400,3412.88,3413.9,3391.8,3398.69,44487372.0
1737720000,3398.69,3404.63,3385.41,3403.48,58305470.0
1737723600,3403.48,3429.0,3390.25,3394.44,113839350.0
1737727200,3394.44,3421.99,3378.04,3398.31,143869564.0
1737730800,3398.34,3408.99,3355.0,3382.62,182652482.0
1737734400,3382.62,3397.06,3375.88,3379.29,76641652.0
1737738000,3379.35,3405.0,3371.76,3396.65,80638944.0
1737741600,3396.6,3408.37,3373.79,3380.06,61571938.0
1737745200,3380.0,3393.91,3363.16,3367.16,95047310.0
1737748800,3367.19,3377.48,3325.47,3327.04,158225220.0
1737752400,3327.75,3345.6,3322.22,3328.33,70830146.0
1737756000,3328.59,3335.82,3321.01,3324.47,47898010.0
1737759600,3324.47,3324.72,3302.5,3309.02,79667410.0
1737763200,3309.02,3312.97,3268.32,3272.36,114215218.0
1737766800,3272.27,3304.88,3267.35,3292.74,75981114.0
1737770400,3292.74,3303.18,3287.86,3293.48,31908786.0
1737774000,3293.48,3322.77,3290.52,3318.01,62089274.0
1737777600,3318.01,3318.57,3296.69,3298.78,41619704.0
1737781200,3298.78,3301.7,3286.6,3295.01,41837638.0
1737784800,3295.01,3302.39,3282.57,3290.84,42042506.0
1737788400,3290.78,3294.18,3281.83,3289.78,31177086.0
1737792000,3289.78,3299.99,3281.43,3289.6,41350052.0
1737795600,3289.6,3291.48,3280.0,3282.3,25686474.0
1737799200,3282.25,3296.12,3270.4,3294.2,64393426.0
1737802800,3294.24,3310.53,3289.62,3305.5,56540872.0
1737806400,3305.5,3306.2,3293.02,3304.78,37528022.0
1737810000,3304.78,3309.07,3299.01,3306.3,28691106.0
1737813600,3306.3,3318.59,3297.0,3314.36,36664870.0
1737817200,3314.41,3343.6,3308.42,3333.02,126783138.0
1737820800,3332.94,3347.91,3328.7,3341.0,60067516.0
1737824400,3341.08,3344.93,3329.09,3343.34,50834736.0
1737828000,3343.34,3347.11,3334.0,3340.79,28862350.0
1737831600,3340.79,3342.99,3333.01,3338.71,18958684.0
1737835200,3338.71,3349.46,3334.15,3335.62,26919424.0
1737838800,3335.66,3341.62,3330.89,3338.49,22254066.0
1737842400,3338.49,3344.78,3330.72,3332.85,16937198.0
1737846000,3332.85,3336.13,3313.36,3317.9,53735534.0
1737849600,3317.9,3326.9,3312.38,3319.74,34181402.0
1737853200,3319.74,3336.98,3317.18,3330.23,29997596.0
1737856800,3330.16,3330.16,3316.39,3327.22,26861986.0
1737860400,3327.22,3349.05,3324.99,3337.47,39360420.0
1737864000,3337.47,3364.99,3335.0,3350.99,60812656.0
1737867600,3350.99,3352.29,3336.82,3341.07,29644874.0
1737871200,3341.07,3346.39,3337.0,3340.36,20394300.0
1737874800,3340.36,3344.23,3328.67,3337.56,24837804.0
1737878400,3337.56,3342.4,3322.11,3330.52,40964058.0
1737882000,3330.52,3331.44,3291.46,3297.06,116578472.0
1737885600,3297.06,3305.58,3294.6,3304.27,37585964.0
1737889200,3304.27,3314.83,3301.35,3310.45,41215532.0
1737892800,3310.45,3310.46,3298.41,3306.64,30648776.0
1737896400,3306.47,3308.32,3299.05,3306.62,41653970.0
1737900000,3306.62,3311.91,3295.61,3309.48,35483260.0
1737903600,3309.48,3319.49,3307.06,3313.61,37547550.0
1737907200,3313.61,3318.63,3306.37,3314.39,35922004.0
1737910800,3314.39,3343.45,3313.81,3336.32,70866966.0
1737914400,3336.32,3341.72,3332.34,3335.83,51959942.0
1737918000,3335.83,3340.69,3328.77,3337.51,32405448.0
1737921600,3337.51,3341.35,3325.55,3328.26,20768510.0
1737925200,3328.3,3328.66,3290.68,3295.01,77584126.0
1737928800,3294.88,3308.55,3280.01,3286.36,69877756.0
1737932400,3286.31,3286.31,3227.47,3230.78,274026736.0
1737936000,3230.65,3252.53,3208.01,3212.62,180964884.0
1737939600,3212.63,3223.16,3186.86,3194.14,165658226.0
1737943200,3193.87,3194.0,3162.32,3169.45,191214386.0
1737946800,3169.45,3197.46,3160.24,3182.11,92065924.0
1737950400,3182.11,3182.11,3152.65,3155.73,87218334.0
1737954000,3155.73,3163.38,3113.02,3139.75,203842944.0
1737957600,3139.8,3148.9,3077.81,3082.76,298234274.0
1737961200,3082.76,3090.27,3020.93,3069.26,415672338.0
1737964800,3069.11,3071.81,3037.23,3064.19,162267474.0
1737968400,3064.24,3088.9,3056.92,3079.48,119649952.0
1737972000,3079.48,3080.18,3032.7,3037.11,115805844.0
1737975600,3037.05,3074.22,3036.34,3057.48,90659514.0
1737979200,3057.48,3121.61,3052.14,3101.53,187794412.0
1737982800,3101.47,3133.28,3087.85,3097.86,231867426.0
1737986400,3097.86,3144.83,3081.86,3136.15,203057890.0
1737990000,3135.72,3150.8,3110.7,3131.09,147629814.0
1737993600,3131.97,3132.04,3074.43,3083.0,203328436.0
1737997200,3082.95,3098.11,3065.24,3071.53,114566258.0
1738000800,3071.57,3087.79,3045.3,3053.88,103725792.0
1738004400,3053.91,3080.93,3053.91,3074.89,83541122.0
1738008000,3074.89,3147.82,3071.83,3145.22,143522924.0
1738011600,3143.97,3237.99,3141.23,3158.16,299739690.0
1738015200,3158.16,3180.06,3145.0,3169.25,79707278.0
1738018800,3169.25,3181.44,3158.71,3180.75,56318916.0
1738022400,3180.79,3202.51,3163.01,3166.22,77481438.0
1738026000,3166.27,3175.57,3150.31,3165.28,59624336.0
1738029600,3164.96,3198.41,3164.14,3191.6,59293696.0
1738033200,3191.56,3216.86,3174.1,3201.47,109284848.0
1738036800,3201.47,3221.53,3196.11,3210.64,83876044.0
1738040400,3210.67,3220.69,3207.19,3211.69,44259070.0
1738044000,3211.69,3214.02,3190.44,3193.55,48991426.0
1738047600,3193.43,3214.7,3187.51,3194.62,50038618.0
1738051200,3194.62,3204.1,3182.01,3197.47,81225676.0
1738054800,3197.42,3200.58,3183.0,3195.72,38138356.0
1738058400,3195.72,3206.32,3187.84,3192.87,39941280.0
1738062000,3192.87,3199.56,3175.47,3185.2,39874048.0
1738065600,3185.2,3194.62,3165.52,3173.72,60379984.0
1738069200,3173.64,3188.0,3169.01,3174.14,39825956.0
1738072800,3174.14,3179.53,3156.0,3171.09,125274148.0
1738076400,3171.34,3213.44,3169.55,3180.15,145496580.0
1738080000,3180.15,3181.81,3130.72,3149.59,141098534.0
1738083600,3149.46,3181.56,3149.05,3166.11,107192478.0
1738087200,3166.07,3176.76,3139.18,3142.6,67871000.0
1738090800,3142.6,3149.32,3118.98,3146.4,100694056.0
1738094400,3146.48,3153.45,3092.03,3094.31,134835852.0
1738098000,3093.42,3113.6,3051.32,3052.43,169849482.0
1738101600,3052.32,3089.94,3038.2,3082.86,165296122.0
1738105200,3082.93,3095.01,3052.51,3075.96,82801056.0
1738108800,3075.96,3116.55,3075.12,3108.9,1274170.0
1738112400,3108.85,3119.0,3097.82,3109.31,1144288.0
1738116000,3109.31,3128.3,3108.69,3112.81,4755046.0
1738119600,3112.74,3131.26,3106.65,3129.02,44437084.0
1738123200,3129.04,3138.89,3121.51,3122.94,51333698.0
1738126800,3122.87,3133.32,3115.46,3129.66,45341342.0
1738130400,3129.66,3148.96,3127.16,3145.88,60770492.0
1738134000,3145.88,3158.0,3137.4,3155.64,54759780.0
1738137600,3155.64,3162.68,3143.0,3146.4,48938372.0
1738141200,3146.4,3147.23,3121.93,3129.27,68754366.0
1738144800,3129.27,3142.05,3119.65,3136.48,46871668.0
1738148400,3136.48,3142.08,3130.31,3133.64,37915812.0
1738152000,3133.64,3138.84,3112.15,3117.69,73520948.0
1738155600,3117.69,3120.73,3087.77,3100.83,123395826.0
1738159200,3100.81,3115.17,3079.41,3095.1,130122046.0
1738162800,3095.81,3117.95,3092.7,3099.65,80143028.0
1 id open high low close volume
2 1735660800 3412.6 3416.0 3390.39 3408.23 102369440.0
3 1735664400 3408.23 3410.38 3329.45 3362.6 239948902.0
4 1735668000 3362.62 3372.14 3349.24 3360.3 87820990.0
5 1735671600 3360.3 3367.9 3342.85 3354.68 42695570.0
6 1735675200 3354.68 3364.47 3336.84 3346.12 54111736.0
7 1735678800 3345.76 3354.28 3331.51 3351.72 48624216.0
8 1735682400 3351.66 3351.66 3327.8 3338.94 44710804.0
9 1735686000 3338.94 3345.03 3327.22 3336.37 37042226.0
10 1735689600 3336.47 3364.49 3334.99 3362.89 57465298.0
11 1735693200 3362.89 3365.08 3341.6 3345.83 34711202.0
12 1735696800 3345.83 3368.02 3345.35 3361.81 34405766.0
13 1735700400 3361.81 3363.0 3350.22 3354.34 21508812.0
14 1735704000 3354.34 3355.78 3338.4 3340.12 45813072.0
15 1735707600 3340.04 3350.57 3339.13 3344.2 29504628.0
16 1735711200 3344.2 3347.33 3335.57 3345.65 26979022.0
17 1735714800 3345.65 3347.77 3338.32 3346.0 19122736.0
18 1735718400 3345.94 3348.0 3330.48 3335.57 39528308.0
19 1735722000 3335.57 3340.16 3313.08 3333.4 129899100.0
20 1735725600 3333.52 3337.99 3325.01 3325.99 32584622.0
21 1735729200 3325.99 3347.73 3322.8 3340.07 45465420.0
22 1735732800 3340.07 3351.21 3337.29 3346.01 39172620.0
23 1735736400 3346.01 3352.78 3331.45 3343.1 51120458.0
24 1735740000 3342.83 3358.89 3327.15 3345.0 82299724.0
25 1735743600 3345.06 3354.24 3332.01 3352.07 51286002.0
26 1735747200 3352.07 3356.14 3331.27 3337.72 49132440.0
27 1735750800 3337.72 3344.37 3322.56 3343.02 49046866.0
28 1735754400 3343.01 3351.47 3332.38 3347.81 36271786.0
29 1735758000 3347.81 3363.82 3338.02 3356.2 55282332.0
30 1735761600 3356.2 3361.76 3351.0 3359.39 38099614.0
31 1735765200 3359.28 3370.87 3352.49 3367.59 51552628.0
32 1735768800 3367.59 3373.97 3357.81 3360.65 43553722.0
33 1735772400 3360.65 3365.99 3352.07 3359.35 33197468.0
34 1735776000 3359.35 3399.41 3354.01 3389.27 123638482.0
35 1735779600 3389.27 3404.76 3377.72 3383.02 72528314.0
36 1735783200 3383.1 3397.9 3376.89 3397.89 35142436.0
37 1735786800 3397.89 3401.77 3386.57 3388.01 28707566.0
38 1735790400 3388.01 3427.38 3387.4 3417.81 124752266.0
39 1735794000 3417.82 3419.18 3404.4 3412.37 64463210.0
40 1735797600 3412.63 3415.73 3401.82 3410.19 37061074.0
41 1735801200 3410.19 3421.77 3408.6 3419.68 42976506.0
42 1735804800 3419.68 3442.8 3414.59 3437.98 81383320.0
43 1735808400 3437.13 3470.72 3433.94 3467.93 117165150.0
44 1735812000 3467.93 3476.09 3457.49 3468.61 95625752.0
45 1735815600 3468.61 3474.99 3457.1 3470.47 55981282.0
46 1735819200 3470.46 3480.37 3465.1 3479.77 71134738.0
47 1735822800 3479.89 3483.94 3459.45 3465.33 135921684.0
48 1735826400 3465.33 3509.87 3439.82 3494.61 298463722.0
49 1735830000 3494.61 3495.56 3455.45 3462.76 137324232.0
50 1735833600 3462.76 3488.75 3447.84 3468.71 102691858.0
51 1735837200 3468.7 3478.07 3429.2 3449.77 130762240.0
52 1735840800 3449.66 3464.67 3439.64 3464.16 96730060.0
53 1735844400 3464.16 3473.57 3458.11 3462.31 52010818.0
54 1735848000 3462.31 3474.61 3450.9 3452.17 41220990.0
55 1735851600 3452.29 3455.39 3442.18 3453.73 48633000.0
56 1735855200 3453.73 3453.75 3419.06 3440.0 62033228.0
57 1735858800 3439.91 3456.41 3437.0 3454.81 33740154.0
58 1735862400 3454.81 3466.23 3445.58 3448.8 49005198.0
59 1735866000 3448.8 3465.02 3442.11 3464.36 64836976.0
60 1735869600 3464.36 3476.32 3455.92 3456.74 51253786.0
61 1735873200 3456.64 3471.96 3455.04 3469.22 41861896.0
62 1735876800 3469.21 3470.11 3455.0 3457.65 33613294.0
63 1735880400 3457.85 3459.99 3443.71 3455.13 57285134.0
64 1735884000 3455.13 3460.9 3441.01 3441.9 36792172.0
65 1735887600 3441.9 3443.62 3431.19 3432.52 64944146.0
66 1735891200 3432.52 3441.96 3422.35 3429.01 71555590.0
67 1735894800 3429.01 3449.99 3428.0 3442.67 45692272.0
68 1735898400 3442.66 3451.63 3437.26 3444.82 34326568.0
69 1735902000 3444.82 3466.53 3444.82 3464.73 51124624.0
70 1735905600 3464.47 3475.49 3460.01 3462.58 57106556.0
71 1735909200 3462.53 3496.26 3462.05 3480.31 136074052.0
72 1735912800 3480.36 3535.47 3479.85 3525.73 252612796.0
73 1735916400 3527.99 3575.99 3518.91 3564.31 266749252.0
74 1735920000 3564.31 3598.54 3564.2 3583.68 236728242.0
75 1735923600 3583.76 3593.0 3572.94 3574.28 77062022.0
76 1735927200 3574.28 3616.82 3573.18 3604.62 145063892.0
77 1735930800 3604.53 3629.68 3601.44 3621.89 136264822.0
78 1735934400 3621.89 3622.32 3599.55 3600.11 82316038.0
79 1735938000 3600.2 3615.64 3594.35 3613.51 60389536.0
80 1735941600 3613.51 3623.2 3609.21 3615.11 41030186.0
81 1735945200 3615.11 3616.87 3603.44 3607.89 55205762.0
82 1735948800 3607.89 3619.9 3601.06 3601.96 52305142.0
83 1735952400 3601.96 3603.52 3581.77 3595.65 60263730.0
84 1735956000 3595.65 3599.45 3582.0 3595.42 35032408.0
85 1735959600 3595.42 3599.48 3590.01 3597.04 28343560.0
86 1735963200 3597.08 3597.18 3583.1 3590.9 31587898.0
87 1735966800 3590.9 3596.15 3585.87 3595.52 27817296.0
88 1735970400 3595.52 3606.6 3594.06 3599.16 34022310.0
89 1735974000 3599.16 3609.0 3591.89 3593.04 43060454.0
90 1735977600 3593.04 3603.11 3584.0 3584.17 82921978.0
91 1735981200 3584.06 3594.99 3582.48 3588.57 39073846.0
92 1735984800 3588.57 3591.98 3570.92 3587.1 48068340.0
93 1735988400 3587.1 3605.05 3583.83 3601.16 55657250.0
94 1735992000 3601.16 3644.09 3599.35 3634.42 152503238.0
95 1735995600 3634.42 3648.59 3626.28 3643.77 105667482.0
96 1735999200 3643.77 3646.0 3631.36 3636.4 63779260.0
97 1736002800 3636.4 3662.37 3592.27 3606.5 238821272.0
98 1736006400 3606.5 3627.64 3600.3 3620.72 76957118.0
99 1736010000 3620.89 3633.52 3618.89 3632.52 40292730.0
100 1736013600 3632.52 3643.7 3618.0 3625.99 47967500.0
101 1736017200 3625.99 3638.39 3623.02 3629.81 24410624.0
102 1736020800 3629.81 3667.58 3629.81 3659.31 70469288.0
103 1736024400 3659.31 3669.95 3653.82 3657.57 60929522.0
104 1736028000 3657.57 3662.13 3645.68 3658.81 34926154.0
105 1736031600 3658.81 3664.88 3649.92 3655.98 35246640.0
106 1736035200 3655.98 3674.56 3646.87 3648.66 55777438.0
107 1736038800 3648.66 3650.3 3630.11 3635.55 52527572.0
108 1736042400 3635.55 3644.01 3633.69 3640.11 24195566.0
109 1736046000 3640.11 3640.9 3628.03 3636.5 20439542.0
110 1736049600 3636.5 3648.0 3635.87 3642.88 29199868.0
111 1736053200 3642.88 3642.9 3629.28 3631.5 26183660.0
112 1736056800 3631.5 3640.66 3626.93 3637.54 20101968.0
113 1736060400 3637.54 3640.13 3628.97 3630.38 19147964.0
114 1736064000 3630.38 3632.11 3607.51 3618.97 102512590.0
115 1736067600 3618.97 3622.41 3604.01 3608.53 47549468.0
116 1736071200 3608.65 3617.6 3601.63 3614.68 40940760.0
117 1736074800 3614.68 3620.13 3608.33 3612.57 30546036.0
118 1736078400 3612.57 3621.77 3603.95 3612.88 43155640.0
119 1736082000 3613.04 3626.65 3611.35 3613.49 37524524.0
120 1736085600 3613.49 3627.36 3592.53 3621.73 135663724.0
121 1736089200 3621.65 3637.67 3618.01 3628.43 75103806.0
122 1736092800 3628.43 3640.01 3623.01 3627.1 60533890.0
123 1736096400 3627.1 3647.35 3621.0 3627.36 52375452.0
124 1736100000 3627.14 3632.37 3611.43 3629.47 43996958.0
125 1736103600 3629.47 3638.96 3625.0 3636.9 25938496.0
126 1736107200 3636.9 3657.0 3627.34 3634.52 61275846.0
127 1736110800 3634.52 3647.21 3632.96 3644.52 23260872.0
128 1736114400 3644.52 3648.89 3633.14 3644.18 23637400.0
129 1736118000 3644.15 3654.47 3631.56 3634.85 35985516.0
130 1736121600 3634.85 3654.52 3620.5 3620.5 61317924.0
131 1736125200 3620.67 3654.84 3608.95 3647.81 86153808.0
132 1736128800 3647.51 3684.08 3644.14 3657.59 182952938.0
133 1736132400 3657.5 3673.87 3652.98 3663.93 46604218.0
134 1736136000 3663.93 3678.2 3659.69 3671.82 46449432.0
135 1736139600 3671.82 3697.99 3666.17 3679.61 99035916.0
136 1736143200 3679.61 3684.04 3664.12 3664.87 52617428.0
137 1736146800 3664.87 3667.1 3641.26 3649.39 93646214.0
138 1736150400 3649.39 3659.4 3635.02 3639.98 82925846.0
139 1736154000 3639.98 3649.36 3639.06 3643.89 28971374.0
140 1736157600 3643.89 3645.87 3631.43 3637.07 42695740.0
141 1736161200 3637.07 3658.44 3635.1 3653.7 56217424.0
142 1736164800 3653.7 3661.82 3640.68 3641.68 59441302.0
143 1736168400 3641.68 3651.94 3623.81 3650.0 96201734.0
144 1736172000 3650.0 3702.32 3621.12 3684.3 289303830.0
145 1736175600 3684.26 3713.01 3670.27 3711.59 260080200.0
146 1736179200 3712.89 3743.7 3690.41 3709.39 272849142.0
147 1736182800 3709.39 3710.16 3654.92 3672.78 176868982.0
148 1736186400 3672.78 3691.03 3661.17 3681.2 68879960.0
149 1736190000 3681.31 3694.94 3674.38 3686.47 39532406.0
150 1736193600 3686.47 3702.68 3671.65 3682.33 59308086.0
151 1736197200 3682.07 3687.78 3665.39 3666.31 51081846.0
152 1736200800 3666.31 3682.56 3666.1 3677.43 38055272.0
153 1736204400 3677.43 3686.36 3667.4 3685.72 28287998.0
154 1736208000 3685.72 3693.4 3672.22 3674.01 48983234.0
155 1736211600 3674.01 3695.78 3661.96 3693.68 48454388.0
156 1736215200 3693.68 3699.99 3675.01 3676.88 41902274.0
157 1736218800 3676.87 3687.99 3672.81 3681.48 34679266.0
158 1736222400 3681.48 3685.53 3672.38 3672.4 22079898.0
159 1736226000 3672.4 3676.15 3657.64 3668.64 45811008.0
160 1736229600 3668.64 3674.79 3663.01 3671.53 29019498.0
161 1736233200 3671.53 3678.99 3661.35 3666.6 29153142.0
162 1736236800 3666.6 3678.49 3659.26 3673.4 41854680.0
163 1736240400 3673.4 3675.58 3652.21 3660.13 57671204.0
164 1736244000 3660.14 3665.0 3650.39 3657.01 42289288.0
165 1736247600 3657.01 3657.99 3625.07 3638.34 132520824.0
166 1736251200 3638.6 3642.32 3625.51 3632.68 67571326.0
167 1736254800 3632.68 3644.9 3630.15 3635.14 48976982.0
168 1736258400 3635.2 3641.18 3523.0 3567.07 333440168.0
169 1736262000 3567.07 3580.49 3410.38 3461.46 1085438710.0
170 1736265600 3461.33 3490.42 3447.53 3456.8 250533314.0
171 1736269200 3456.8 3469.33 3420.12 3441.09 227652302.0
172 1736272800 3440.99 3458.14 3411.8 3420.51 182306610.0
173 1736276400 3420.51 3436.46 3374.36 3384.93 267051616.0
174 1736280000 3384.59 3399.26 3362.16 3395.32 175652002.0
175 1736283600 3395.27 3412.8 3359.81 3361.96 139760754.0
176 1736287200 3362.09 3396.25 3355.13 3395.21 96223134.0
177 1736290800 3395.21 3395.21 3373.61 3379.37 51490032.0
178 1736294400 3379.37 3413.55 3376.91 3410.01 87357960.0
179 1736298000 3410.09 3410.12 3373.39 3389.82 70746830.0
180 1736301600 3389.82 3402.98 3381.2 3381.23 51129254.0
181 1736305200 3381.23 3386.39 3342.71 3359.34 186577674.0
182 1736308800 3359.34 3372.73 3342.07 3347.27 105866768.0
183 1736312400 3347.27 3371.89 3336.08 3350.48 104936154.0
184 1736316000 3350.48 3361.34 3306.03 3307.77 211327564.0
185 1736319600 3307.8 3358.07 3306.71 3353.19 146187366.0
186 1736323200 3353.19 3375.59 3349.83 3364.56 101254772.0
187 1736326800 3364.57 3372.85 3345.0 3345.89 75539896.0
188 1736330400 3345.89 3371.99 3345.16 3360.9 69829694.0
189 1736334000 3360.9 3366.39 3321.76 3348.44 164453210.0
190 1736337600 3348.44 3359.3 3337.6 3338.59 85930986.0
191 1736341200 3338.61 3365.29 3338.61 3357.39 89649230.0
192 1736344800 3357.21 3380.52 3346.3 3369.27 151342344.0
193 1736348400 3368.94 3384.66 3332.0 3345.99 206886030.0
194 1736352000 3345.99 3347.06 3310.44 3313.07 148369138.0
195 1736355600 3313.11 3318.93 3207.46 3262.23 658990620.0
196 1736359200 3262.21 3329.38 3257.5 3281.58 286190748.0
197 1736362800 3281.99 3308.69 3270.47 3279.62 140264688.0
198 1736366400 3279.57 3290.0 3265.01 3284.51 65621974.0
199 1736370000 3284.51 3303.67 3268.87 3297.9 74963226.0
200 1736373600 3297.85 3332.86 3297.28 3331.31 80470748.0
201 1736377200 3331.31 3333.47 3314.73 3325.46 41780554.0
202 1736380800 3325.46 3342.07 3316.67 3340.7 60166482.0
203 1736384400 3340.12 3356.49 3333.9 3344.64 63614256.0
204 1736388000 3344.64 3349.59 3305.94 3339.6 165240584.0
205 1736391600 3339.6 3341.35 3315.56 3324.06 63469448.0
206 1736395200 3323.71 3342.24 3311.0 3339.0 67512222.0
207 1736398800 3338.96 3341.19 3323.42 3327.38 39150924.0
208 1736402400 3327.38 3333.77 3313.68 3314.92 41707280.0
209 1736406000 3314.92 3323.33 3281.3 3288.19 154505570.0
210 1736409600 3288.19 3325.89 3263.38 3308.99 192210656.0
211 1736413200 3309.07 3326.72 3305.94 3316.68 65498146.0
212 1736416800 3316.68 3321.07 3283.42 3310.84 106064710.0
213 1736420400 3310.84 3325.5 3292.07 3300.36 76143062.0
214 1736424000 3300.36 3309.23 3279.89 3294.89 72951552.0
215 1736427600 3294.89 3297.76 3211.02 3219.8 310900906.0
216 1736431200 3219.6 3251.76 3209.02 3249.62 207212678.0
217 1736434800 3249.62 3335.0 3242.45 3318.81 240337982.0
218 1736438400 3318.81 3326.2 3286.7 3300.79 164041718.0
219 1736442000 3300.79 3302.94 3234.38 3249.49 184871012.0
220 1736445600 3249.49 3269.11 3244.47 3258.78 103697430.0
221 1736449200 3259.07 3267.62 3190.01 3193.56 229460404.0
222 1736452800 3193.54 3212.74 3155.96 3194.13 302442148.0
223 1736456400 3194.12 3224.91 3189.44 3206.78 90139568.0
224 1736460000 3205.89 3238.13 3186.39 3222.7 89771046.0
225 1736463600 3222.7 3231.72 3208.6 3217.86 49759112.0
226 1736467200 3218.13 3232.61 3212.86 3221.74 54670720.0
227 1736470800 3221.74 3238.89 3212.52 3235.53 61826016.0
228 1736474400 3235.53 3258.78 3229.27 3239.91 73960624.0
229 1736478000 3240.12 3254.85 3237.3 3253.05 39189052.0
230 1736481600 3253.05 3263.57 3245.37 3252.64 52641914.0
231 1736485200 3252.78 3280.15 3241.27 3262.78 81991616.0
232 1736488800 3262.6 3279.35 3258.56 3276.45 46459632.0
233 1736492400 3276.45 3312.38 3269.49 3294.65 142743074.0
234 1736496000 3294.65 3300.61 3286.36 3294.77 54960336.0
235 1736499600 3294.77 3309.3 3289.02 3301.2 55245834.0
236 1736503200 3301.2 3319.92 3296.47 3316.89 63228784.0
237 1736506800 3316.89 3318.66 3294.49 3309.74 69342416.0
238 1736510400 3309.74 3311.0 3291.98 3309.36 67812524.0
239 1736514000 3309.25 3315.95 3215.36 3242.94 442746528.0
240 1736517600 3242.94 3277.64 3235.03 3255.47 229753402.0
241 1736521200 3253.81 3274.86 3193.21 3243.69 363287258.0
242 1736524800 3243.54 3260.64 3231.0 3246.19 141134442.0
243 1736528400 3246.11 3320.22 3241.43 3313.36 173307620.0
244 1736532000 3313.27 3313.27 3280.14 3285.21 117654418.0
245 1736535600 3285.76 3297.7 3269.11 3293.79 84001780.0
246 1736539200 3293.79 3293.8 3256.27 3258.81 62458836.0
247 1736542800 3258.71 3273.33 3256.01 3264.13 32978326.0
248 1736546400 3264.13 3280.1 3258.48 3272.36 35630396.0
249 1736550000 3272.36 3274.17 3263.04 3265.52 22914060.0
250 1736553600 3265.52 3268.92 3256.51 3264.4 38075382.0
251 1736557200 3264.4 3266.68 3235.13 3244.52 61301216.0
252 1736560800 3244.52 3250.87 3236.17 3246.5 29747936.0
253 1736564400 3246.5 3247.11 3230.52 3235.88 28924308.0
254 1736568000 3235.88 3242.0 3228.51 3237.53 32303354.0
255 1736571600 3237.53 3244.92 3231.48 3244.35 33205960.0
256 1736575200 3244.35 3249.5 3236.31 3236.33 28510900.0
257 1736578800 3236.33 3243.13 3224.17 3234.72 38537850.0
258 1736582400 3234.72 3239.07 3215.12 3223.37 48376530.0
259 1736586000 3223.37 3243.45 3222.27 3243.01 49518806.0
260 1736589600 3243.01 3255.31 3242.22 3255.26 79756560.0
261 1736593200 3255.26 3279.23 3252.9 3272.68 95103116.0
262 1736596800 3272.68 3280.0 3266.71 3271.65 39652500.0
263 1736600400 3271.65 3274.82 3257.51 3266.4 49449588.0
264 1736604000 3266.4 3278.98 3257.26 3277.3 42866688.0
265 1736607600 3277.2 3281.01 3265.16 3270.07 31206676.0
266 1736611200 3270.07 3277.14 3261.0 3274.11 31282780.0
267 1736614800 3274.11 3274.9 3257.7 3270.89 40054362.0
268 1736618400 3270.89 3279.01 3266.11 3277.06 18851470.0
269 1736622000 3276.96 3282.49 3268.28 3277.47 31217294.0
270 1736625600 3277.47 3299.48 3274.61 3298.28 40594708.0
271 1736629200 3298.28 3319.01 3298.05 3305.69 62717802.0
272 1736632800 3305.69 3307.36 3284.5 3287.56 40714280.0
273 1736636400 3287.56 3293.32 3280.33 3281.85 29895820.0
274 1736640000 3281.85 3286.11 3277.98 3282.18 22834780.0
275 1736643600 3282.18 3288.32 3273.02 3287.87 25636570.0
276 1736647200 3287.87 3288.96 3278.26 3288.87 17973236.0
277 1736650800 3288.87 3289.88 3277.02 3285.27 19745114.0
278 1736654400 3285.27 3288.62 3279.52 3282.52 17536690.0
279 1736658000 3282.52 3284.4 3273.11 3278.51 18182922.0
280 1736661600 3278.51 3280.29 3266.38 3269.24 28730928.0
281 1736665200 3269.24 3272.82 3262.31 3265.63 38470516.0
282 1736668800 3265.62 3270.61 3233.02 3238.36 122652126.0
283 1736672400 3238.45 3243.5 3223.13 3236.97 107510624.0
284 1736676000 3236.97 3244.82 3232.45 3243.12 47696088.0
285 1736679600 3243.12 3257.11 3239.67 3251.63 50138698.0
286 1736683200 3251.86 3264.27 3246.51 3249.24 57619188.0
287 1736686800 3249.24 3270.58 3246.94 3266.0 68944450.0
288 1736690400 3266.0 3279.9 3265.0 3267.83 73240184.0
289 1736694000 3267.83 3294.5 3264.0 3284.65 79888684.0
290 1736697600 3284.65 3286.99 3267.61 3280.51 43169660.0
291 1736701200 3280.51 3291.46 3277.19 3287.9 46143554.0
292 1736704800 3287.81 3298.89 3279.33 3283.73 47041518.0
293 1736708400 3283.73 3287.97 3274.66 3279.11 25800656.0
294 1736712000 3279.11 3288.49 3272.07 3280.55 23003516.0
295 1736715600 3280.63 3281.94 3262.59 3265.11 44126248.0
296 1736719200 3265.12 3267.41 3232.85 3239.17 101407078.0
297 1736722800 3239.17 3267.36 3237.68 3265.69 44761358.0
298 1736726400 3265.69 3338.19 3263.9 3307.67 252955806.0
299 1736730000 3307.43 3311.66 3251.27 3260.13 196644388.0
300 1736733600 3260.13 3269.95 3236.0 3254.9 121374346.0
301 1736737200 3254.9 3265.89 3234.02 3241.24 90367330.0
302 1736740800 3241.24 3259.58 3236.46 3237.36 78938608.0
303 1736744400 3237.36 3237.8 3211.68 3224.18 119089336.0
304 1736748000 3224.49 3232.3 3180.01 3190.13 176832932.0
305 1736751600 3190.1 3208.74 3181.93 3200.53 86710800.0
306 1736755200 3200.53 3205.45 3159.9 3168.74 156073064.0
307 1736758800 3168.74 3176.15 3119.18 3155.01 234976700.0
308 1736762400 3155.01 3155.99 3106.07 3117.96 317611886.0
309 1736766000 3118.75 3123.04 3055.09 3056.7 378759676.0
310 1736769600 3056.4 3084.95 3039.54 3045.72 305548852.0
311 1736773200 3045.89 3090.3 3032.3 3059.44 249979524.0
312 1736776800 3059.44 3060.11 2909.6 3033.47 974243346.0
313 1736780400 3033.59 3076.35 3025.13 3047.42 366822882.0
314 1736784000 3047.42 3058.66 3004.86 3008.65 234479378.0
315 1736787600 3007.87 3035.84 3003.01 3019.36 152995168.0
316 1736791200 3019.36 3032.98 2985.02 3006.39 179997976.0
317 1736794800 3006.38 3036.47 2991.8 3023.97 125369102.0
318 1736798400 3023.97 3103.38 3010.35 3090.15 177752432.0
319 1736802000 3090.41 3118.78 3081.97 3112.72 165786786.0
320 1736805600 3112.72 3141.66 3110.97 3130.64 116974672.0
321 1736809200 3130.64 3139.43 3124.38 3136.15 47544220.0
322 1736812800 3136.15 3147.25 3124.06 3132.57 84185166.0
323 1736816400 3132.57 3157.97 3132.19 3138.01 94074596.0
324 1736820000 3137.9 3165.79 3130.36 3155.98 85221592.0
325 1736823600 3155.98 3174.3 3153.45 3157.58 54405210.0
326 1736827200 3157.58 3174.12 3157.58 3171.39 55857890.0
327 1736830800 3171.23 3181.33 3158.29 3160.65 79933988.0
328 1736834400 3160.65 3187.06 3156.26 3182.95 73104704.0
329 1736838000 3182.95 3189.0 3169.86 3170.4 56505048.0
330 1736841600 3170.4 3191.27 3168.36 3181.91 74257186.0
331 1736845200 3182.0 3255.21 3176.59 3242.42 259501370.0
332 1736848800 3242.42 3242.89 3219.7 3233.75 124964948.0
333 1736852400 3233.75 3234.23 3209.7 3216.28 67811012.0
334 1736856000 3216.12 3218.73 3179.51 3182.39 163014218.0
335 1736859600 3182.5 3231.74 3178.0 3207.21 199494486.0
336 1736863200 3207.22 3232.31 3186.1 3190.41 130742936.0
337 1736866800 3190.94 3214.98 3186.11 3197.86 137337984.0
338 1736870400 3197.86 3202.94 3171.03 3189.99 137636112.0
339 1736874000 3189.99 3211.7 3182.72 3211.33 80978048.0
340 1736877600 3211.1 3231.4 3205.89 3223.37 92417500.0
341 1736881200 3223.37 3234.31 3211.09 3212.9 62213378.0
342 1736884800 3212.9 3224.69 3193.52 3221.24 82723252.0
343 1736888400 3221.24 3232.5 3211.25 3214.72 50505536.0
344 1736892000 3214.72 3239.2 3212.11 3233.81 35697584.0
345 1736895600 3233.81 3236.6 3221.18 3223.99 28458870.0
346 1736899200 3223.99 3241.26 3216.09 3220.18 62474718.0
347 1736902800 3220.18 3244.58 3215.73 3228.96 71656158.0
348 1736906400 3228.96 3238.69 3205.0 3211.66 70425488.0
349 1736910000 3211.77 3240.66 3207.26 3239.89 54759212.0
350 1736913600 3239.88 3251.11 3220.79 3225.01 81473270.0
351 1736917200 3224.99 3234.39 3213.86 3228.57 46760866.0
352 1736920800 3228.57 3231.82 3215.17 3229.14 47369732.0
353 1736924400 3229.14 3249.69 3228.61 3231.31 72666604.0
354 1736928000 3231.31 3246.86 3228.52 3230.98 60786620.0
355 1736931600 3231.1 3236.52 3195.34 3199.21 97527064.0
356 1736935200 3199.21 3217.14 3196.79 3208.08 62126134.0
357 1736938800 3208.08 3208.96 3185.53 3198.3 77459828.0
358 1736942400 3198.3 3210.72 3185.4 3200.66 78921674.0
359 1736946000 3200.66 3297.25 3200.4 3297.01 361680060.0
360 1736949600 3297.01 3330.61 3274.57 3328.32 260514000.0
361 1736953200 3328.37 3353.09 3324.53 3333.17 216457060.0
362 1736956800 3333.07 3365.41 3332.56 3338.3 139245078.0
363 1736960400 3338.3 3357.46 3322.99 3324.68 90410118.0
364 1736964000 3324.68 3373.77 3324.68 3370.89 81676352.0
365 1736967600 3370.8 3442.18 3366.66 3433.76 263310966.0
366 1736971200 3433.76 3472.38 3431.66 3432.83 208944138.0
367 1736974800 3432.81 3445.86 3426.0 3431.39 62340338.0
368 1736978400 3431.39 3434.99 3417.53 3429.39 51207524.0
369 1736982000 3429.48 3451.12 3419.23 3449.82 66010384.0
370 1736985600 3449.82 3458.48 3385.69 3397.95 171382692.0
371 1736989200 3397.95 3412.55 3391.65 3402.58 46722624.0
372 1736992800 3402.58 3405.0 3380.39 3384.03 61431958.0
373 1736996400 3384.03 3386.8 3345.74 3362.11 132369822.0
374 1737000000 3362.11 3374.53 3360.45 3373.24 55905782.0
375 1737003600 3373.24 3376.07 3364.58 3366.9 27209092.0
376 1737007200 3366.9 3386.02 3361.78 3378.89 55504360.0
377 1737010800 3378.86 3389.29 3375.89 3382.41 42026166.0
378 1737014400 3382.41 3384.0 3301.88 3315.42 213550818.0
379 1737018000 3315.44 3335.0 3298.01 3334.8 173270654.0
380 1737021600 3334.8 3340.99 3328.0 3332.2 59671834.0
381 1737025200 3332.87 3354.87 3320.07 3349.64 111186100.0
382 1737028800 3349.65 3363.28 3340.11 3355.43 97407238.0
383 1737032400 3355.53 3357.3 3309.0 3327.07 167514778.0
384 1737036000 3327.1 3341.53 3264.28 3276.1 285205966.0
385 1737039600 3276.25 3332.09 3268.53 3331.98 228397622.0
386 1737043200 3331.98 3360.66 3329.4 3339.22 152861984.0
387 1737046800 3338.77 3364.41 3329.91 3342.69 93468544.0
388 1737050400 3342.69 3349.79 3308.93 3324.61 90234800.0
389 1737054000 3324.61 3344.94 3318.01 3343.35 43458370.0
390 1737057600 3343.35 3351.99 3324.68 3335.77 53289036.0
391 1737061200 3335.71 3336.78 3310.16 3319.09 54644580.0
392 1737064800 3319.09 3319.31 3267.03 3296.7 131717852.0
393 1737068400 3296.7 3311.39 3289.02 3306.93 68247846.0
394 1737072000 3306.93 3316.78 3306.59 3312.78 42675412.0
395 1737075600 3312.78 3393.76 3312.72 3384.73 214952370.0
396 1737079200 3384.73 3396.23 3354.05 3372.07 140006948.0
397 1737082800 3372.07 3376.06 3357.4 3359.98 47167210.0
398 1737086400 3359.98 3371.42 3346.44 3369.69 64118896.0
399 1737090000 3369.69 3374.77 3358.19 3365.51 44641394.0
400 1737093600 3365.51 3374.7 3363.39 3366.38 39763556.0
401 1737097200 3366.38 3393.91 3361.3 3371.36 70940042.0
402 1737100800 3371.36 3412.78 3371.0 3405.9 121892422.0
403 1737104400 3405.9 3413.03 3399.07 3402.51 70929662.0
404 1737108000 3402.51 3437.78 3401.1 3426.64 102788236.0
405 1737111600 3426.64 3429.5 3415.53 3422.1 55018198.0
406 1737115200 3422.1 3425.46 3399.89 3406.78 90512196.0
407 1737118800 3406.78 3422.93 3394.96 3400.81 77679768.0
408 1737122400 3400.76 3431.89 3400.75 3427.7 167275558.0
409 1737126000 3427.49 3449.69 3403.1 3420.33 195084666.0
410 1737129600 3420.32 3447.59 3410.53 3436.43 111256436.0
411 1737133200 3436.43 3441.9 3406.02 3413.26 100510326.0
412 1737136800 3413.38 3428.83 3409.07 3410.49 47213594.0
413 1737140400 3410.49 3443.03 3409.73 3430.79 91962986.0
414 1737144000 3431.02 3524.4 3424.26 3514.04 286751750.0
415 1737147600 3514.04 3524.53 3465.44 3472.64 136440486.0
416 1737151200 3472.64 3486.56 3466.01 3468.91 61781218.0
417 1737154800 3468.91 3483.87 3461.49 3472.39 47196678.0
418 1737158400 3472.39 3492.94 3467.34 3485.83 52615116.0
419 1737162000 3485.83 3485.83 3453.85 3464.95 63843980.0
420 1737165600 3464.95 3473.28 3446.9 3450.06 47257378.0
421 1737169200 3450.11 3455.0 3366.79 3382.77 229697520.0
422 1737172800 3382.77 3394.52 3350.01 3364.52 172058940.0
423 1737176400 3364.52 3369.99 3290.01 3292.89 274237194.0
424 1737180000 3292.89 3339.39 3291.66 3312.76 153000770.0
425 1737183600 3312.76 3314.37 3280.01 3286.46 147604794.0
426 1737187200 3286.47 3294.66 3251.0 3291.85 228254978.0
427 1737190800 3291.85 3299.87 3252.31 3269.83 127768426.0
428 1737194400 3269.89 3276.99 3225.14 3265.78 252550352.0
429 1737198000 3265.81 3323.48 3247.76 3310.18 227271112.0
430 1737201600 3310.29 3320.91 3273.3 3288.68 159370596.0
431 1737205200 3288.68 3322.36 3278.33 3321.84 137949644.0
432 1737208800 3321.84 3325.22 3287.76 3295.86 97189442.0
433 1737212400 3295.86 3346.2 3283.95 3305.77 219267024.0
434 1737216000 3305.89 3315.72 3252.51 3252.51 243473644.0
435 1737219600 3252.51 3284.8 3252.12 3257.2 97599068.0
436 1737223200 3256.5 3283.03 3249.0 3263.66 83528110.0
437 1737226800 3263.54 3292.49 3260.39 3289.08 56544316.0
438 1737230400 3289.08 3290.88 3256.74 3264.87 58021088.0
439 1737234000 3264.88 3285.06 3262.08 3273.72 37319280.0
440 1737237600 3273.72 3287.67 3270.02 3279.36 30291248.0
441 1737241200 3279.42 3320.34 3278.22 3306.69 83215168.0
442 1737244800 3306.69 3322.38 3297.72 3315.68 66796494.0
443 1737248400 3315.68 3365.18 3312.9 3352.57 155449194.0
444 1737252000 3352.57 3377.32 3346.9 3352.47 82240816.0
445 1737255600 3352.47 3365.32 3332.52 3334.97 97009222.0
446 1737259200 3334.97 3337.32 3276.02 3282.51 202282652.0
447 1737262800 3282.51 3299.78 3258.18 3298.57 105321972.0
448 1737266400 3298.57 3299.93 3280.91 3282.12 47257870.0
449 1737270000 3282.18 3292.37 3261.31 3275.02 88322326.0
450 1737273600 3275.02 3277.15 3215.0 3221.19 203332442.0
451 1737277200 3221.19 3233.18 3143.11 3226.34 411242284.0
452 1737280800 3225.66 3226.18 3173.02 3174.2 166786984.0
453 1737284400 3174.3 3188.53 3131.0 3149.56 209689408.0
454 1737288000 3150.33 3210.59 3144.26 3205.26 164299906.0
455 1737291600 3205.26 3277.31 3193.14 3273.7 251270350.0
456 1737295200 3275.24 3395.99 3258.42 3380.19 863763538.0
457 1737298800 3380.11 3424.81 3352.82 3383.79 333831610.0
458 1737302400 3383.77 3424.04 3377.57 3410.83 168812328.0
459 1737306000 3410.88 3448.14 3385.96 3442.35 194255198.0
460 1737309600 3442.35 3449.0 3406.9 3434.0 106325700.0
461 1737313200 3433.4 3434.0 3407.59 3419.94 57312166.0
462 1737316800 3419.94 3432.95 3351.04 3378.22 144020792.0
463 1737320400 3378.22 3379.4 3207.05 3235.01 501866746.0
464 1737324000 3232.5 3311.84 3156.18 3265.77 478996130.0
465 1737327600 3265.76 3265.76 3160.07 3213.52 466762210.0
466 1737331200 3214.05 3225.31 3142.73 3170.28 407986910.0
467 1737334800 3170.27 3219.48 3165.19 3200.27 229060286.0
468 1737338400 3199.96 3273.76 3196.01 3243.54 218587436.0
469 1737342000 3244.04 3279.99 3227.01 3271.39 119161842.0
470 1737345600 3271.35 3298.81 3249.6 3269.87 100450292.0
471 1737349200 3269.87 3318.14 3266.79 3290.91 124554022.0
472 1737352800 3290.91 3454.72 3285.41 3417.53 388228564.0
473 1737356400 3417.41 3441.9 3351.89 3383.02 374577926.0
474 1737360000 3382.95 3412.04 3380.02 3392.15 127096766.0
475 1737363600 3392.15 3411.93 3352.99 3364.15 186871672.0
476 1737367200 3364.15 3391.99 3341.78 3354.39 126612530.0
477 1737370800 3354.39 3388.33 3334.21 3375.69 172373108.0
478 1737374400 3375.69 3379.6 3256.4 3303.82 367009686.0
479 1737378000 3303.93 3354.87 3295.01 3342.28 210560350.0
480 1737381600 3342.23 3361.6 3329.61 3358.56 154930784.0
481 1737385200 3358.55 3378.98 3315.21 3335.57 241523322.0
482 1737388800 3335.93 3390.0 3276.81 3380.16 274158310.0
483 1737392400 3379.9 3384.07 3205.0 3292.24 795072372.0
484 1737396000 3292.24 3341.58 3283.72 3330.16 213855650.0
485 1737399600 3330.04 3364.11 3308.4 3342.92 128630890.0
486 1737403200 3342.92 3344.32 3313.98 3320.27 77237838.0
487 1737406800 3320.27 3337.16 3280.51 3284.42 82249858.0
488 1737410400 3284.36 3324.16 3255.28 3318.25 103096784.0
489 1737414000 3318.14 3320.28 3260.59 3283.21 98151492.0
490 1737417600 3283.21 3289.47 3220.47 3225.66 167574272.0
491 1737421200 3225.9 3260.77 3203.89 3250.4 181075574.0
492 1737424800 3250.4 3272.75 3227.81 3256.73 97124780.0
493 1737428400 3256.73 3269.67 3248.01 3262.23 63734320.0
494 1737432000 3262.23 3262.25 3212.81 3246.37 95284392.0
495 1737435600 3246.37 3253.9 3216.03 3224.39 73892594.0
496 1737439200 3224.65 3253.97 3212.82 3241.15 98098922.0
497 1737442800 3241.15 3266.0 3234.55 3254.01 67830494.0
498 1737446400 3254.0 3262.97 3233.55 3253.27 67584610.0
499 1737450000 3253.27 3276.4 3249.82 3275.74 77660896.0
500 1737453600 3275.74 3308.8 3270.41 3302.06 104765974.0
501 1737457200 3302.06 3313.19 3291.81 3304.39 91283102.0
502 1737460800 3304.39 3325.85 3293.07 3306.62 128372258.0
503 1737464400 3306.62 3314.49 3288.96 3308.85 80976134.0
504 1737468000 3308.71 3333.73 3279.0 3288.51 211256600.0
505 1737471600 3288.51 3300.99 3261.77 3294.1 128559286.0
506 1737475200 3294.1 3349.14 3289.36 3313.34 197211854.0
507 1737478800 3313.15 3356.04 3307.09 3350.37 90531198.0
508 1737482400 3350.37 3367.88 3329.87 3345.17 100399176.0
509 1737486000 3345.18 3346.29 3317.24 3331.74 80784936.0
510 1737489600 3331.74 3339.63 3303.34 3313.41 70082146.0
511 1737493200 3313.43 3335.71 3301.87 3331.61 54339844.0
512 1737496800 3331.58 3346.58 3326.0 3333.06 38895058.0
513 1737500400 3333.91 3334.32 3307.27 3326.74 73269766.0
514 1737504000 3326.74 3365.96 3322.53 3361.54 73640766.0
515 1737507600 3361.54 3361.83 3321.61 3328.53 68953758.0
516 1737511200 3328.34 3346.78 3322.0 3343.32 51151860.0
517 1737514800 3343.32 3347.85 3327.2 3330.54 33271698.0
518 1737518400 3330.54 3332.93 3315.84 3331.15 33810516.0
519 1737522000 3331.15 3339.33 3317.01 3317.66 29934040.0
520 1737525600 3317.66 3323.48 3301.61 3308.82 50870486.0
521 1737529200 3308.82 3310.36 3286.18 3287.05 76036546.0
522 1737532800 3286.97 3300.02 3273.0 3298.39 92349262.0
523 1737536400 3298.39 3303.49 3289.1 3297.4 35948534.0
524 1737540000 3297.4 3307.4 3287.82 3306.99 40550278.0
525 1737543600 3306.99 3328.83 3303.3 3325.53 53272540.0
526 1737547200 3325.53 3331.45 3310.14 3315.9 52994384.0
527 1737550800 3315.85 3318.31 3279.25 3283.32 100473366.0
528 1737554400 3283.39 3310.99 3266.7 3292.02 165657884.0
529 1737558000 3292.72 3304.69 3268.95 3277.5 108866836.0
530 1737561600 3277.5 3282.91 3261.0 3277.1 97706330.0
531 1737565200 3277.15 3287.01 3271.02 3284.6 48476310.0
532 1737568800 3284.6 3290.85 3239.08 3248.93 96991712.0
533 1737572400 3249.38 3279.0 3247.52 3261.51 73598538.0
534 1737576000 3261.51 3276.21 3253.01 3255.86 46359000.0
535 1737579600 3255.82 3264.32 3240.0 3258.42 64803018.0
536 1737583200 3258.42 3265.69 3231.89 3237.63 52779412.0
537 1737586800 3237.63 3245.99 3221.53 3241.77 78166668.0
538 1737590400 3241.77 3260.81 3237.04 3252.92 56714310.0
539 1737594000 3252.92 3257.59 3220.0 3234.28 65753656.0
540 1737597600 3234.34 3236.57 3203.23 3222.26 94598842.0
541 1737601200 3222.48 3242.35 3214.38 3225.64 57395280.0
542 1737604800 3225.71 3230.89 3182.66 3196.01 114327136.0
543 1737608400 3196.01 3220.5 3195.34 3213.89 55114374.0
544 1737612000 3213.89 3223.98 3203.26 3207.1 39191160.0
545 1737615600 3207.1 3232.44 3197.39 3231.96 53561668.0
546 1737619200 3231.96 3232.44 3207.44 3209.22 45550378.0
547 1737622800 3209.26 3221.14 3191.13 3195.94 60758744.0
548 1737626400 3195.94 3212.68 3187.34 3203.3 65237070.0
549 1737630000 3203.3 3216.15 3194.82 3212.78 49857888.0
550 1737633600 3212.78 3217.94 3188.52 3202.62 78595334.0
551 1737637200 3202.62 3242.4 3201.12 3233.01 108985424.0
552 1737640800 3232.89 3285.36 3221.81 3274.6 249651856.0
553 1737644400 3274.6 3280.91 3225.01 3258.51 281277612.0
554 1737648000 3258.51 3296.73 3252.0 3253.65 190993782.0
555 1737651600 3253.64 3270.76 3230.02 3264.89 108032146.0
556 1737655200 3264.92 3269.43 3234.0 3239.9 70643910.0
557 1737658800 3239.9 3245.0 3193.09 3203.76 157291960.0
558 1737662400 3203.71 3294.1 3195.86 3246.15 442292904.0
559 1737666000 3246.11 3255.52 3212.77 3247.4 120420326.0
560 1737669600 3247.85 3322.98 3245.19 3321.94 160218202.0
561 1737673200 3321.66 3347.53 3311.27 3337.88 118336168.0
562 1737676800 3337.88 3348.99 3284.11 3284.72 117342552.0
563 1737680400 3284.69 3325.37 3283.51 3297.47 90561650.0
564 1737684000 3297.49 3313.1 3278.58 3284.64 67232158.0
565 1737687600 3285.21 3311.93 3275.0 3301.41 91279686.0
566 1737691200 3301.35 3339.92 3291.13 3332.72 87852684.0
567 1737694800 3332.45 3409.47 3328.55 3409.22 199536164.0
568 1737698400 3409.28 3420.61 3378.01 3385.27 167874148.0
569 1737702000 3385.32 3400.36 3371.39 3380.59 82619272.0
570 1737705600 3380.59 3415.57 3374.6 3400.57 104233816.0
571 1737709200 3400.58 3412.03 3391.01 3400.87 62308630.0
572 1737712800 3400.73 3414.21 3390.53 3412.88 57566642.0
573 1737716400 3412.88 3413.9 3391.8 3398.69 44487372.0
574 1737720000 3398.69 3404.63 3385.41 3403.48 58305470.0
575 1737723600 3403.48 3429.0 3390.25 3394.44 113839350.0
576 1737727200 3394.44 3421.99 3378.04 3398.31 143869564.0
577 1737730800 3398.34 3408.99 3355.0 3382.62 182652482.0
578 1737734400 3382.62 3397.06 3375.88 3379.29 76641652.0
579 1737738000 3379.35 3405.0 3371.76 3396.65 80638944.0
580 1737741600 3396.6 3408.37 3373.79 3380.06 61571938.0
581 1737745200 3380.0 3393.91 3363.16 3367.16 95047310.0
582 1737748800 3367.19 3377.48 3325.47 3327.04 158225220.0
583 1737752400 3327.75 3345.6 3322.22 3328.33 70830146.0
584 1737756000 3328.59 3335.82 3321.01 3324.47 47898010.0
585 1737759600 3324.47 3324.72 3302.5 3309.02 79667410.0
586 1737763200 3309.02 3312.97 3268.32 3272.36 114215218.0
587 1737766800 3272.27 3304.88 3267.35 3292.74 75981114.0
588 1737770400 3292.74 3303.18 3287.86 3293.48 31908786.0
589 1737774000 3293.48 3322.77 3290.52 3318.01 62089274.0
590 1737777600 3318.01 3318.57 3296.69 3298.78 41619704.0
591 1737781200 3298.78 3301.7 3286.6 3295.01 41837638.0
592 1737784800 3295.01 3302.39 3282.57 3290.84 42042506.0
593 1737788400 3290.78 3294.18 3281.83 3289.78 31177086.0
594 1737792000 3289.78 3299.99 3281.43 3289.6 41350052.0
595 1737795600 3289.6 3291.48 3280.0 3282.3 25686474.0
596 1737799200 3282.25 3296.12 3270.4 3294.2 64393426.0
597 1737802800 3294.24 3310.53 3289.62 3305.5 56540872.0
598 1737806400 3305.5 3306.2 3293.02 3304.78 37528022.0
599 1737810000 3304.78 3309.07 3299.01 3306.3 28691106.0
600 1737813600 3306.3 3318.59 3297.0 3314.36 36664870.0
601 1737817200 3314.41 3343.6 3308.42 3333.02 126783138.0
602 1737820800 3332.94 3347.91 3328.7 3341.0 60067516.0
603 1737824400 3341.08 3344.93 3329.09 3343.34 50834736.0
604 1737828000 3343.34 3347.11 3334.0 3340.79 28862350.0
605 1737831600 3340.79 3342.99 3333.01 3338.71 18958684.0
606 1737835200 3338.71 3349.46 3334.15 3335.62 26919424.0
607 1737838800 3335.66 3341.62 3330.89 3338.49 22254066.0
608 1737842400 3338.49 3344.78 3330.72 3332.85 16937198.0
609 1737846000 3332.85 3336.13 3313.36 3317.9 53735534.0
610 1737849600 3317.9 3326.9 3312.38 3319.74 34181402.0
611 1737853200 3319.74 3336.98 3317.18 3330.23 29997596.0
612 1737856800 3330.16 3330.16 3316.39 3327.22 26861986.0
613 1737860400 3327.22 3349.05 3324.99 3337.47 39360420.0
614 1737864000 3337.47 3364.99 3335.0 3350.99 60812656.0
615 1737867600 3350.99 3352.29 3336.82 3341.07 29644874.0
616 1737871200 3341.07 3346.39 3337.0 3340.36 20394300.0
617 1737874800 3340.36 3344.23 3328.67 3337.56 24837804.0
618 1737878400 3337.56 3342.4 3322.11 3330.52 40964058.0
619 1737882000 3330.52 3331.44 3291.46 3297.06 116578472.0
620 1737885600 3297.06 3305.58 3294.6 3304.27 37585964.0
621 1737889200 3304.27 3314.83 3301.35 3310.45 41215532.0
622 1737892800 3310.45 3310.46 3298.41 3306.64 30648776.0
623 1737896400 3306.47 3308.32 3299.05 3306.62 41653970.0
624 1737900000 3306.62 3311.91 3295.61 3309.48 35483260.0
625 1737903600 3309.48 3319.49 3307.06 3313.61 37547550.0
626 1737907200 3313.61 3318.63 3306.37 3314.39 35922004.0
627 1737910800 3314.39 3343.45 3313.81 3336.32 70866966.0
628 1737914400 3336.32 3341.72 3332.34 3335.83 51959942.0
629 1737918000 3335.83 3340.69 3328.77 3337.51 32405448.0
630 1737921600 3337.51 3341.35 3325.55 3328.26 20768510.0
631 1737925200 3328.3 3328.66 3290.68 3295.01 77584126.0
632 1737928800 3294.88 3308.55 3280.01 3286.36 69877756.0
633 1737932400 3286.31 3286.31 3227.47 3230.78 274026736.0
634 1737936000 3230.65 3252.53 3208.01 3212.62 180964884.0
635 1737939600 3212.63 3223.16 3186.86 3194.14 165658226.0
636 1737943200 3193.87 3194.0 3162.32 3169.45 191214386.0
637 1737946800 3169.45 3197.46 3160.24 3182.11 92065924.0
638 1737950400 3182.11 3182.11 3152.65 3155.73 87218334.0
639 1737954000 3155.73 3163.38 3113.02 3139.75 203842944.0
640 1737957600 3139.8 3148.9 3077.81 3082.76 298234274.0
641 1737961200 3082.76 3090.27 3020.93 3069.26 415672338.0
642 1737964800 3069.11 3071.81 3037.23 3064.19 162267474.0
643 1737968400 3064.24 3088.9 3056.92 3079.48 119649952.0
644 1737972000 3079.48 3080.18 3032.7 3037.11 115805844.0
645 1737975600 3037.05 3074.22 3036.34 3057.48 90659514.0
646 1737979200 3057.48 3121.61 3052.14 3101.53 187794412.0
647 1737982800 3101.47 3133.28 3087.85 3097.86 231867426.0
648 1737986400 3097.86 3144.83 3081.86 3136.15 203057890.0
649 1737990000 3135.72 3150.8 3110.7 3131.09 147629814.0
650 1737993600 3131.97 3132.04 3074.43 3083.0 203328436.0
651 1737997200 3082.95 3098.11 3065.24 3071.53 114566258.0
652 1738000800 3071.57 3087.79 3045.3 3053.88 103725792.0
653 1738004400 3053.91 3080.93 3053.91 3074.89 83541122.0
654 1738008000 3074.89 3147.82 3071.83 3145.22 143522924.0
655 1738011600 3143.97 3237.99 3141.23 3158.16 299739690.0
656 1738015200 3158.16 3180.06 3145.0 3169.25 79707278.0
657 1738018800 3169.25 3181.44 3158.71 3180.75 56318916.0
658 1738022400 3180.79 3202.51 3163.01 3166.22 77481438.0
659 1738026000 3166.27 3175.57 3150.31 3165.28 59624336.0
660 1738029600 3164.96 3198.41 3164.14 3191.6 59293696.0
661 1738033200 3191.56 3216.86 3174.1 3201.47 109284848.0
662 1738036800 3201.47 3221.53 3196.11 3210.64 83876044.0
663 1738040400 3210.67 3220.69 3207.19 3211.69 44259070.0
664 1738044000 3211.69 3214.02 3190.44 3193.55 48991426.0
665 1738047600 3193.43 3214.7 3187.51 3194.62 50038618.0
666 1738051200 3194.62 3204.1 3182.01 3197.47 81225676.0
667 1738054800 3197.42 3200.58 3183.0 3195.72 38138356.0
668 1738058400 3195.72 3206.32 3187.84 3192.87 39941280.0
669 1738062000 3192.87 3199.56 3175.47 3185.2 39874048.0
670 1738065600 3185.2 3194.62 3165.52 3173.72 60379984.0
671 1738069200 3173.64 3188.0 3169.01 3174.14 39825956.0
672 1738072800 3174.14 3179.53 3156.0 3171.09 125274148.0
673 1738076400 3171.34 3213.44 3169.55 3180.15 145496580.0
674 1738080000 3180.15 3181.81 3130.72 3149.59 141098534.0
675 1738083600 3149.46 3181.56 3149.05 3166.11 107192478.0
676 1738087200 3166.07 3176.76 3139.18 3142.6 67871000.0
677 1738090800 3142.6 3149.32 3118.98 3146.4 100694056.0
678 1738094400 3146.48 3153.45 3092.03 3094.31 134835852.0
679 1738098000 3093.42 3113.6 3051.32 3052.43 169849482.0
680 1738101600 3052.32 3089.94 3038.2 3082.86 165296122.0
681 1738105200 3082.93 3095.01 3052.51 3075.96 82801056.0
682 1738108800 3075.96 3116.55 3075.12 3108.9 1274170.0
683 1738112400 3108.85 3119.0 3097.82 3109.31 1144288.0
684 1738116000 3109.31 3128.3 3108.69 3112.81 4755046.0
685 1738119600 3112.74 3131.26 3106.65 3129.02 44437084.0
686 1738123200 3129.04 3138.89 3121.51 3122.94 51333698.0
687 1738126800 3122.87 3133.32 3115.46 3129.66 45341342.0
688 1738130400 3129.66 3148.96 3127.16 3145.88 60770492.0
689 1738134000 3145.88 3158.0 3137.4 3155.64 54759780.0
690 1738137600 3155.64 3162.68 3143.0 3146.4 48938372.0
691 1738141200 3146.4 3147.23 3121.93 3129.27 68754366.0
692 1738144800 3129.27 3142.05 3119.65 3136.48 46871668.0
693 1738148400 3136.48 3142.08 3130.31 3133.64 37915812.0
694 1738152000 3133.64 3138.84 3112.15 3117.69 73520948.0
695 1738155600 3117.69 3120.73 3087.77 3100.83 123395826.0
696 1738159200 3100.81 3115.17 3079.41 3095.1 130122046.0
697 1738162800 3095.81 3117.95 3092.7 3099.65 80143028.0

View File

@@ -0,0 +1,172 @@
# -*- coding: utf-8 -*-
"""
Bitmart 多周期K线数据抓取 - 供回测与实盘使用
与 bitmart/回测.py、bitmart/抓取多周期K线.py 相同的 API 调用方式
"""
import time
import csv
import os
from typing import List, Dict, Optional
try:
from loguru import logger
except ImportError:
import logging
logger = logging.getLogger(__name__)
# 项目根目录为 lm_codebitmart 包在根目录
import sys
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
ROOT_DIR = os.path.dirname(SCRIPT_DIR)
if ROOT_DIR not in sys.path:
sys.path.insert(0, ROOT_DIR)
# 默认 API与 bitmart/回测.py 一致,回测仅拉数据可不填有效 key
# APIContract 在 fetch_klines / fetch_multi_timeframe 内按需导入,以便 --no-api 回测不依赖 bitmart
DEFAULT_API_KEY = "a0fb7b98464fd9bcce67e7c519d58ec10d0c38a8"
DEFAULT_SECRET_KEY = "4eaeba78e77aeaab1c2027f846a276d164f264a44c2c1bb1c5f3be50c8de1ca5"
DEFAULT_MEMO = "合约交易"
CONTRACT_SYMBOL = "ETHUSDT"
def _format_bar(k: dict) -> dict:
"""API 单根K线 -> 统一格式id 为秒时间戳"""
return {
"id": int(k["timestamp"]),
"open": float(k["open_price"]),
"high": float(k["high_price"]),
"low": float(k["low_price"]),
"close": float(k["close_price"]),
"volume": float(k.get("volume", 0)),
}
def fetch_klines(
contract_api: "APIContract",
step: int,
start_time: int,
end_time: int,
symbol: str = CONTRACT_SYMBOL,
) -> List[Dict]:
"""
拉取指定周期的K线与 bitmart 回测抓取方式一致)。
:param contract_api: bitmart.api_contract.APIContract 实例
:param step: K线周期分钟如 5/15/60
:param start_time: 开始时间戳(秒)
:param end_time: 结束时间戳(秒)
:param symbol: 合约符号
:return: [{"id", "open", "high", "low", "close", "volume"}, ...],按 id 升序
"""
all_data: List[Dict] = []
existing_ids = set()
request_interval = step * 60 * 500 # 每次最多约 500 根
current_start = start_time
while current_start < end_time:
current_end = min(current_start + request_interval, end_time)
try:
response = contract_api.get_kline(
contract_symbol=symbol,
step=step,
start_time=current_start,
end_time=current_end,
)[0]
if response.get("code") != 1000:
logger.warning(f"get_kline code={response.get('code')}, msg={response.get('msg')}")
time.sleep(1)
current_start = current_end
continue
data = response.get("data", [])
except Exception as e:
logger.warning(f"get_kline 异常 step={step} {e}60秒后重试")
time.sleep(60)
continue
for k in data:
k_id = int(k["timestamp"])
if k_id in existing_ids:
continue
existing_ids.add(k_id)
all_data.append(_format_bar(k))
if len(data) < 500:
current_start = current_end
else:
all_data.sort(key=lambda x: x["id"])
current_start = all_data[-1]["id"] + 1
time.sleep(0.25)
all_data.sort(key=lambda x: x["id"])
return all_data
def fetch_multi_timeframe(
start_time: int,
end_time: int,
steps: List[int] = None,
api_key: str = DEFAULT_API_KEY,
secret_key: str = DEFAULT_SECRET_KEY,
memo: str = DEFAULT_MEMO,
symbol: str = CONTRACT_SYMBOL,
) -> Dict[int, List[Dict]]:
"""
拉取多周期K线5/15/60供回测使用。
:return: { step: [kline_list] }
"""
steps = steps or [5, 15, 60]
from bitmart.api_contract import APIContract
api = APIContract(api_key, secret_key, memo, timeout=(5, 15))
result = {}
for step in steps:
logger.info(f"抓取 {step} 分钟 K 线: {start_time} ~ {end_time}")
result[step] = fetch_klines(api, step, start_time, end_time, symbol)
logger.info(f" -> {len(result[step])}")
return result
def save_klines_csv(klines: List[Dict], path: str) -> None:
"""将K线保存为 CSVid, open, high, low, close, volume"""
if not klines:
return
cols = ["id", "open", "high", "low", "close", "volume"]
with open(path, "w", newline="", encoding="utf-8") as f:
w = csv.DictWriter(f, fieldnames=cols)
w.writeheader()
for row in klines:
w.writerow({k: row.get(k) for k in cols})
logger.info(f"已保存 {len(klines)} 条到 {path}")
def load_klines_csv(path: str) -> List[Dict]:
"""从 CSV 加载K线"""
if not os.path.isfile(path):
return []
with open(path, "r", encoding="utf-8") as f:
r = csv.DictReader(f)
rows = list(r)
out = []
for row in rows:
out.append({
"id": int(row["id"]),
"open": float(row["open"]),
"high": float(row["high"]),
"low": float(row["low"]),
"close": float(row["close"]),
"volume": float(row.get("volume", 0)),
})
out.sort(key=lambda x: x["id"])
return out
if __name__ == "__main__":
import datetime
# 示例:拉取最近约 30 天 5/15/60 分钟数据并保存
end_ts = int(time.time())
start_ts = end_ts - 30 * 24 * 3600
data_dir = os.path.join(SCRIPT_DIR, "data")
os.makedirs(data_dir, exist_ok=True)
data = fetch_multi_timeframe(start_ts, end_ts, steps=[5, 15, 60])
for step, klines in data.items():
path = os.path.join(data_dir, f"kline_{step}m.csv")
save_klines_csv(klines, path)

View File

@@ -0,0 +1,86 @@
# -*- coding: utf-8 -*-
"""
技术指标EMA、ATR
"""
from typing import List, Dict, Optional
def ema(series: List[float], period: int) -> List[Optional[float]]:
"""EMA(period),前 period-1 个为 None"""
if not series or period < 1:
return []
k = 2.0 / (period + 1)
out: List[Optional[float]] = [None] * (period - 1)
s = sum(series[:period])
out.append(s / period)
for i in range(period, len(series)):
val = series[i] * k + out[-1] * (1 - k) # type: ignore
out.append(val)
return out
def atr(high: List[float], low: List[float], close: List[float], period: int) -> List[Optional[float]]:
"""ATR(period),前 period 个为 None"""
n = len(close)
if n < period + 1 or len(high) != n or len(low) != n:
return [None] * n
tr_list: List[float] = []
for i in range(n):
if i == 0:
tr_list.append(high[0] - low[0])
else:
tr = max(
high[i] - low[i],
abs(high[i] - close[i - 1]),
abs(low[i] - close[i - 1])
)
tr_list.append(tr)
return ema(tr_list, period)
def get_ema_atr_from_klines(klines: List[Dict], ema_period: int, atr_period: int
) -> tuple:
"""
从K线列表计算收盘价 EMA 和 ATR。
返回 (ema_list, atr_list),长度与 klines 一致。
"""
close = [float(k["close"]) for k in klines]
high = [float(k["high"]) for k in klines]
low = [float(k["low"]) for k in klines]
ema_list = ema(close, ema_period)
atr_list = atr(high, low, close, atr_period)
return ema_list, atr_list
def align_higher_tf_ema(
klines_5m: List[Dict],
klines_higher: List[Dict],
ema_fast: int,
ema_slow: int
) -> List[Dict]:
"""
根据更高周期K线计算 EMA并按 5 分钟时间对齐。
返回列表长度与 klines_5m 一致,每项为 {"ema_fast": float, "ema_slow": float} 或 None。
"""
if not klines_higher or len(klines_higher) < ema_slow:
return [{}] * len(klines_5m)
close_hi = [float(k["close"]) for k in klines_higher]
ema_f = ema(close_hi, ema_fast)
ema_s = ema(close_hi, ema_slow)
id_hi = [k["id"] for k in klines_higher]
result = []
for k5 in klines_5m:
t = k5["id"]
# 当前 5m 时刻所属的更高周期:取 <= t 的最后一根
idx = -1
for i, tid in enumerate(id_hi):
if tid <= t:
idx = i
else:
break
if idx >= ema_slow - 1 and ema_f[idx] is not None and ema_s[idx] is not None:
result.append({"ema_fast": ema_f[idx], "ema_slow": ema_s[idx]})
else:
result.append({})
return result

View File

@@ -0,0 +1,305 @@
# -*- coding: utf-8 -*-
"""
自适应三分位趋势策略 - 核心逻辑
趋势过滤、动态阈值、信号确认、市场状态
"""
from typing import List, Dict, Optional, Tuple
import sys
import os
ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
if ROOT_DIR not in sys.path:
sys.path.insert(0, ROOT_DIR)
from adaptive_third_strategy.config import (
MIN_BODY_ATR_RATIO,
MIN_VOLATILITY_PERCENT,
EMA_SHORT,
EMA_LONG_FAST,
EMA_LONG_SLOW,
EMA_MID_FAST,
EMA_MID_SLOW,
ATR_PERIOD,
VOLATILITY_COEF_CLAMP,
BASE_COEF,
TREND_FAVOR_COEF,
TREND_AGAINST_COEF,
TREND_MODE,
CONFIRM_REQUIRED,
VOLUME_MA_PERIOD,
VOLUME_RATIO_THRESHOLD,
REVERSE_BREAK_MULT,
MIN_BARS_SINCE_ENTRY,
FORBIDDEN_PERIODS,
ATR_PAUSE_MULT,
STRONG_TREND_COEF,
RANGE_COEF,
HIGH_VOL_EXTRA_CONFIRM,
)
from adaptive_third_strategy.indicators import (
get_ema_atr_from_klines,
align_higher_tf_ema,
ema,
)
def get_body_size(candle: Dict) -> float:
return abs(float(candle["open"]) - float(candle["close"]))
def is_bullish(candle: Dict) -> bool:
return float(candle["close"]) > float(candle["open"])
def get_min_body_threshold(price: float, atr_value: Optional[float]) -> float:
"""有效K线最小实体 = max(ATR*0.1, 价格*0.05%)"""
min_vol = price * MIN_VOLATILITY_PERCENT
if atr_value is not None and atr_value > 0:
min_vol = max(min_vol, atr_value * MIN_BODY_ATR_RATIO)
return min_vol
def find_valid_prev_bar(
all_data: List[Dict],
current_idx: int,
atr_series: List[Optional[float]],
min_body_override: Optional[float] = None,
) -> Tuple[Optional[int], Optional[Dict]]:
"""从当前索引往前找实体>=阈值的K线。阈值 = max(ATR*0.1, 价格*0.05%)"""
if current_idx <= 0:
return None, None
for i in range(current_idx - 1, -1, -1):
prev = all_data[i]
body = get_body_size(prev)
price = float(prev["close"])
atr_val = atr_series[i] if i < len(atr_series) else None
th = min_body_override if min_body_override is not None else get_min_body_threshold(price, atr_val)
if body >= th:
return i, prev
return None, None
def get_trend(
klines_5m: List[Dict],
idx_5m: int,
ema_5m: List[Optional[float]],
ema_15m_align: List[Dict],
ema_60m_align: List[Dict],
) -> str:
"""
多时间框架趋势。返回 "long" / "short" / "neutral"
长期1h EMA50 vs EMA200中期15m EMA20 vs EMA50短期5m close vs EMA9。
ema_*_align: 与 5m 对齐的列表,每项 {"ema_fast", "ema_slow"}。
"""
if idx_5m >= len(klines_5m):
return "neutral"
curr = klines_5m[idx_5m]
close_5 = float(curr["close"])
# 短期
ema9 = ema_5m[idx_5m] if idx_5m < len(ema_5m) else None
short_bull = (ema9 is not None and close_5 > ema9)
# 中期
mid = ema_15m_align[idx_5m] if idx_5m < len(ema_15m_align) else {}
mid_bull = (mid.get("ema_fast") is not None and mid.get("ema_slow") is not None
and mid["ema_fast"] > mid["ema_slow"])
# 长期
long_d = ema_60m_align[idx_5m] if idx_5m < len(ema_60m_align) else {}
long_bull = (long_d.get("ema_fast") is not None and long_d.get("ema_slow") is not None
and long_d["ema_fast"] > long_d["ema_slow"])
if TREND_MODE == "aggressive":
return "long" if short_bull else "short"
if TREND_MODE == "conservative":
if mid_bull and short_bull:
return "long"
if not mid_bull and not short_bull:
return "short"
return "neutral"
# strict
if long_bull and mid_bull and short_bull:
return "long"
if not long_bull and not mid_bull and not short_bull:
return "short"
return "neutral"
def get_dynamic_trigger_levels(
prev: Dict,
atr_value: float,
trend: str,
market_state: str = "normal",
) -> Tuple[Optional[float], Optional[float]]:
"""
动态三分位触发价。
波动率系数 = clamp(实体/ATR, 0.3, 3.0),调整系数 = 0.33 * 波动率系数。
顺势方向 ×0.8,逆势 ×1.2。
"""
body = get_body_size(prev)
if body < 1e-6 or atr_value <= 0:
return None, None
vol_coef = body / atr_value
vol_coef = max(VOLATILITY_COEF_CLAMP[0], min(VOLATILITY_COEF_CLAMP[1], vol_coef))
adj = BASE_COEF * vol_coef
if market_state == "strong_trend":
adj = STRONG_TREND_COEF
elif market_state == "range":
adj = RANGE_COEF
p_close = float(prev["close"])
if trend == "long":
long_adj = adj * TREND_FAVOR_COEF
short_adj = adj * TREND_AGAINST_COEF
elif trend == "short":
long_adj = adj * TREND_AGAINST_COEF
short_adj = adj * TREND_FAVOR_COEF
else:
long_adj = short_adj = adj
long_trigger = p_close + body * long_adj
short_trigger = p_close - body * short_adj
return long_trigger, short_trigger
def check_signal_confirm(
curr: Dict,
direction: str,
trigger_price: float,
all_data: List[Dict],
current_idx: int,
volume_ma: Optional[float],
required: int = CONFIRM_REQUIRED,
) -> int:
"""
确认条件计数:收盘价确认、成交量确认、动量确认。
返回满足的个数。
"""
count = 0
c_close = float(curr["close"])
c_volume = float(curr.get("volume", 0))
# 1. 收盘价确认
if direction == "long" and c_close >= trigger_price:
count += 1
elif direction == "short" and c_close <= trigger_price:
count += 1
# 2. 成交量确认
if volume_ma is not None and volume_ma > 0 and c_volume >= volume_ma * VOLUME_RATIO_THRESHOLD:
count += 1
# 3. 动量确认当前K线实体方向与信号一致
if direction == "long" and is_bullish(curr):
count += 1
elif direction == "short" and not is_bullish(curr):
count += 1
return count
def in_forbidden_period(ts_sec: int) -> bool:
"""是否在禁止交易时段(按 UTC+8 小时:分)"""
from datetime import datetime, timezone
try:
dt = datetime.fromtimestamp(ts_sec, tz=timezone.utc)
except Exception:
dt = datetime.utcfromtimestamp(ts_sec)
# 转 UTC+8
hour = (dt.hour + 8) % 24
minute = dt.minute
for h1, m1, h2, m2 in FORBIDDEN_PERIODS:
t1 = h1 * 60 + m1
t2 = h2 * 60 + m2
t = hour * 60 + minute
if t1 <= t < t2:
return True
return False
def get_market_state(
atr_value: float,
atr_avg: Optional[float],
trend: str,
) -> str:
"""normal / strong_trend / range / high_vol"""
if atr_avg is not None and atr_avg > 0 and atr_value >= atr_avg * ATR_PAUSE_MULT:
return "high_vol"
if trend in ("long", "short") and atr_avg is not None and atr_value > atr_avg * 1.2:
return "strong_trend"
if trend == "neutral":
return "range"
return "normal"
def check_trigger(
all_data: List[Dict],
current_idx: int,
atr_series: List[Optional[float]],
ema_5m: List[Optional[float]],
ema_15m_align: List[Dict],
ema_60m_align: List[Dict],
volume_ma_list: Optional[List[Optional[float]]] = None,
use_confirm: bool = True,
) -> Tuple[Optional[str], Optional[float], Optional[int], Optional[Dict]]:
"""
检查当前K线是否产生有效信号含趋势过滤与确认
返回 (方向, 触发价, 有效前一根索引, 有效前一根K线) 或 (None, None, None, None)。
"""
if current_idx <= 0 or current_idx >= len(all_data):
return None, None, None, None
curr = all_data[current_idx]
valid_prev_idx, prev = find_valid_prev_bar(all_data, current_idx, atr_series)
if prev is None:
return None, None, None, None
atr_val = atr_series[current_idx] if current_idx < len(atr_series) else None
if atr_val is None or atr_val <= 0:
return None, None, None, None
trend = get_trend(
all_data, current_idx, ema_5m, ema_15m_align, ema_60m_align,
)
atr_avg = None
if atr_series:
valid_atr = [x for x in atr_series[: current_idx + 1] if x is not None and x > 0]
if len(valid_atr) >= ATR_PERIOD:
atr_avg = sum(valid_atr) / len(valid_atr)
market_state = get_market_state(atr_val, atr_avg, trend)
if market_state == "high_vol":
return None, None, None, None
long_trigger, short_trigger = get_dynamic_trigger_levels(prev, atr_val, trend, market_state)
if long_trigger is None:
return None, None, None, None
c_high = float(curr["high"])
c_low = float(curr["low"])
long_triggered = c_high >= long_trigger
short_triggered = c_low <= short_trigger
direction = None
trigger_price = None
if long_triggered and short_triggered:
c_open = float(curr["open"])
if abs(c_open - short_trigger) <= abs(c_open - long_trigger):
direction, trigger_price = "short", short_trigger
else:
direction, trigger_price = "long", long_trigger
elif short_triggered:
direction, trigger_price = "short", short_trigger
elif long_triggered:
direction, trigger_price = "long", long_trigger
if direction is None:
return None, None, None, None
# 趋势过滤:逆势不交易(可选,这里做过滤)
if trend == "long" and direction == "short":
return None, None, None, None
if trend == "short" and direction == "long":
return None, None, None, None
# 禁止时段
if in_forbidden_period(curr["id"]):
return None, None, None, None
# 信号确认
if use_confirm and CONFIRM_REQUIRED > 0:
vol_ma = volume_ma_list[current_idx] if volume_ma_list and current_idx < len(volume_ma_list) else None
n = check_signal_confirm(curr, direction, trigger_price, all_data, current_idx, vol_ma, CONFIRM_REQUIRED)
if n < CONFIRM_REQUIRED:
return None, None, None, None
return direction, trigger_price, valid_prev_idx, prev
def build_volume_ma(klines: List[Dict], period: int = VOLUME_MA_PERIOD) -> List[Optional[float]]:
"""前 period-1 为 None之后为 volume 的 SMA"""
vol = [float(k.get("volume", 0)) for k in klines]
out: List[Optional[float]] = [None] * (period - 1)
for i in range(period - 1, len(vol)):
out.append(sum(vol[i - period + 1 : i + 1]) / period)
return out

View File

@@ -0,0 +1,187 @@
# -*- coding: utf-8 -*-
"""
自适应三分位趋势策略 - 实盘交易
拉取 Bitmart 5/15/60 分钟数据,计算信号,执行开平仓(沿用 交易/bitmart-三分之一策略交易 的浏览器/API 逻辑)
"""
import os
import sys
import time
import datetime
from typing import List, Dict, Optional, Tuple
try:
from loguru import logger
except ImportError:
import logging
logger = logging.getLogger(__name__)
ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
if ROOT_DIR not in sys.path:
sys.path.insert(0, ROOT_DIR)
from bitmart.api_contract import APIContract
from adaptive_third_strategy.config import (
STEP_5M,
STEP_15M,
STEP_60M,
ATR_PERIOD,
EMA_SHORT,
EMA_MID_FAST,
EMA_MID_SLOW,
EMA_LONG_FAST,
EMA_LONG_SLOW,
BASE_POSITION_PERCENT,
MAX_POSITION_PERCENT,
CONTRACT_SYMBOL,
)
from adaptive_third_strategy.indicators import get_ema_atr_from_klines, align_higher_tf_ema
from adaptive_third_strategy.strategy_core import check_trigger, build_volume_ma
from adaptive_third_strategy.data_fetcher import fetch_klines, _format_bar
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
class AdaptiveThirdStrategyTrader:
"""实盘获取多周期K线 -> 策略信号 -> 开平仓(可接浏览器或纯 API"""
def __init__(
self,
api_key: str,
secret_key: str,
memo: str = "合约交易",
symbol: str = CONTRACT_SYMBOL,
bit_id: Optional[str] = None,
):
self.api_key = api_key
self.secret_key = secret_key
self.memo = memo
self.symbol = symbol
self.bit_id = bit_id
self.contractAPI = APIContract(api_key, secret_key, memo, timeout=(5, 15))
self.check_interval = 3
self.last_trigger_kline_id: Optional[int] = None
self.last_trigger_direction: Optional[str] = None
self.last_trade_kline_id: Optional[int] = None
self.position_direction: int = 0 # 1 多 -1 空 0 无
def get_klines_multi(self) -> Tuple[List[Dict], List[Dict], List[Dict]]:
"""拉取当前 5/15/60 分钟 K 线(最近约 3 小时足够算 EMA/ATR"""
end_ts = int(time.time())
start_ts = end_ts - 3600 * 3
k5 = fetch_klines(self.contractAPI, STEP_5M, start_ts, end_ts, self.symbol)
k15 = fetch_klines(self.contractAPI, STEP_15M, start_ts, end_ts, self.symbol)
k60 = fetch_klines(self.contractAPI, STEP_60M, start_ts, end_ts, self.symbol)
return k5, k15, k60
def get_position_status(self) -> bool:
"""查询当前持仓,更新 self.position_direction"""
try:
response = self.contractAPI.get_position(contract_symbol=self.symbol)[0]
if response.get("code") != 1000:
return False
positions = response.get("data", [])
if not positions:
self.position_direction = 0
return True
self.position_direction = 1 if positions[0].get("position_type") == 1 else -1
return True
except Exception as e:
logger.error(f"持仓查询异常: {e}")
return False
def check_realtime_signal(
self,
klines_5m: List[Dict],
klines_15m: List[Dict],
klines_60m: List[Dict],
) -> Tuple[Optional[str], Optional[float], Optional[Dict]]:
"""
基于当前 K 线(最后一根未收盘)检测实时信号。
返回 (方向, 触发价, 当前K线) 或 (None, None, None)。
"""
if len(klines_5m) < ATR_PERIOD + 2:
return None, None, None
from adaptive_third_strategy.indicators import get_ema_atr_from_klines
from adaptive_third_strategy.strategy_core import check_trigger
ema_5m, atr_5m = get_ema_atr_from_klines(klines_5m, EMA_SHORT, ATR_PERIOD)
ema_15m_align = align_higher_tf_ema(klines_5m, klines_15m, EMA_MID_FAST, EMA_MID_SLOW)
ema_60m_align = align_higher_tf_ema(klines_5m, klines_60m, EMA_LONG_FAST, EMA_LONG_SLOW)
volume_ma = build_volume_ma(klines_5m)
curr_idx = len(klines_5m) - 1
direction, trigger_price, _, _ = check_trigger(
klines_5m, curr_idx, atr_5m, ema_5m, ema_15m_align, ema_60m_align, volume_ma, use_confirm=True
)
curr = klines_5m[curr_idx]
curr_id = curr["id"]
if direction is None:
return None, None, None
if self.last_trigger_kline_id == curr_id and self.last_trigger_direction == direction:
return None, None, None
if self.last_trade_kline_id == curr_id:
return None, None, None
if (direction == "long" and self.position_direction == 1) or (direction == "short" and self.position_direction == -1):
return None, None, None
return direction, trigger_price, curr
def run_loop(self, ding_callback=None):
"""
主循环:拉数据 -> 检测信号 -> 若需交易则调用开平仓(需外部实现或注入)。
ding_callback(msg, error=False) 可选,用于钉钉通知。
"""
def ding(msg: str, error: bool = False):
if ding_callback:
ding_callback(msg, error)
else:
if error:
logger.error(msg)
else:
logger.info(msg)
logger.info("自适应三分位趋势策略实盘启动,按 Bitmart 方式拉取 5/15/60 分钟数据")
while True:
try:
k5, k15, k60 = self.get_klines_multi()
if len(k5) < ATR_PERIOD + 2:
time.sleep(self.check_interval)
continue
if not self.get_position_status():
time.sleep(self.check_interval)
continue
direction, trigger_price, curr = self.check_realtime_signal(k5, k15, k60)
if direction and trigger_price is not None and curr is not None:
curr_id = curr["id"]
ding(f"信号: {direction} @ {trigger_price:.2f} 当前K线 id={curr_id}")
# 这里接入你的开平仓实现:平仓 + 开单(可调用 交易/bitmart-三分之一策略交易 的 平仓/开单 或 API 下单)
# 示例:仅记录,不实际下单
self.last_trigger_kline_id = curr_id
self.last_trigger_direction = direction
self.last_trade_kline_id = curr_id
time.sleep(self.check_interval)
except Exception as e:
logger.exception(e)
time.sleep(60)
def main():
import argparse
parser = argparse.ArgumentParser(description="自适应三分位趋势策略实盘")
parser.add_argument("--api-key", default="", help="Bitmart API Key")
parser.add_argument("--secret-key", default="", help="Bitmart Secret Key")
parser.add_argument("--bit-id", default="", help="比特浏览器 ID若用浏览器下单")
args = parser.parse_args()
api_key = args.api_key or os.environ.get("BITMART_API_KEY", "a0fb7b98464fd9bcce67e7c519d58ec10d0c38a8")
secret_key = args.secret_key or os.environ.get("BITMART_SECRET_KEY", "4eaeba78e77aeaab1c2027f846a276d164f264a44c2c1bb1c5f3be50c8de1ca5")
trader = AdaptiveThirdStrategyTrader(api_key, secret_key, bit_id=args.bit_id or None)
try:
from 交易.tools import send_dingtalk_message
def ding(msg, error=False):
prefix = "❌自适应三分位:" if error else "🔔自适应三分位:"
send_dingtalk_message(f"{prefix}{msg}")
except Exception:
def ding(msg, error=False):
logger.info(msg)
trader.run_loop(ding_callback=ding)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,762 @@
"""
BitMart 三分之一回归策略交易(双向触发版)
使用5分钟K线周期实时监测
策略规则:
1. 触发价格计算基于有效的前一根K线实体>=0.1
- 做多触发价格 = 收盘价 + 实体/3从收盘价往上涨1/3
- 做空触发价格 = 收盘价 - 实体/3从收盘价往下跌1/3
2. 信号触发条件:
- 当前K线最高价 >= 做多触发价格 → 做多信号
- 当前K线最低价 <= 做空触发价格 → 做空信号
- 方向以当前收盘相对前一根收盘为准:当前收盘在前一根之上偏多(只开多/不开空),之下偏空(只开空/不开多);双触时也按此选方向,避免先探后拉/先拉后砸误开反手。
3. 执行逻辑:
- 做多时遇到做空信号 -> 平多并反手开空
- 做空时遇到做多信号 -> 平空并反手开多
- 同一根K线内若先开空后价格回调到「做多触发价」开仓价+上一根实体/3则平空开多反之先开多后跌到做空触发价则平多开空。同一根K线内仅允许一次反手防止频繁来回开仓。
示例1阳线
前一根K线开盘3000收盘3100阳线实体=100
- 做多触发价格 = 3100 + 33 = 3133继续上涨做多
- 做空触发价格 = 3100 - 33 = 3067回调做空←当前跌到这里就做空
示例2阴线
前一根K线开盘3100收盘3000阴线实体=100
- 做多触发价格 = 3000 + 33 = 3033反弹做多
- 做空触发价格 = 3000 - 33 = 2967继续下跌做空
"""
import time
import datetime
from tqdm import tqdm
from loguru import logger
from bit_tools import openBrowser
from DrissionPage import ChromiumPage,ChromiumOptions
from bitmart.api_contract import APIContract
from 交易.tools import send_dingtalk_message
class BitmartOneThirdStrategy:
def __init__(self, bit_id):
self.page: ChromiumPage | None = None
self.api_key = "6104088c65a68d7e53df5d9395b67d78e555293a"
self.secret_key = "a8b14312330d8e6b9b09acfd972b34e32022fdfa9f2b06f0a0a31723b873fd01"
self.memo = "me"
self.contract_symbol = "ETHUSDT"
self.contractAPI = APIContract(self.api_key, self.secret_key, self.memo, timeout=(5, 15))
self.start = 0 # 持仓状态: -1 空, 0 无, 1 多
self.direction = None
self.pbar = tqdm(total=15, desc="等待K线", ncols=80) # 5分钟周期
self.last_kline_time = None
self.leverage = "40" # 高杠杆(全仓模式下可开更大仓位)
self.open_type = "cross" # 全仓模式
self.risk_percent = 0.01 # 每次开仓使用可用余额的 1%
self.open_avg_price = None # 开仓价格
self.current_amount = None # 持仓量
self.bit_id = bit_id
# 三分之一策略参数
self.min_body_size = 0.1 # 最小实体大小
self.kline_step = 15 # K线周期5分钟
self.kline_count = 20 # 获取的K线数量用于向前查找有效K线
# 实时监测参数
self.check_interval = 3 # 检测间隔(秒)
self.last_trigger_kline_id = None # 记录上次触发信号的K线ID避免同一K线重复触发
self.last_trigger_direction = None # 记录上次触发的方向
self.last_trade_kline_id = None # 记录上次实际交易的K线ID防止同一K线内频繁反手
# ========================= 三分之一策略核心函数 =========================
def is_bullish(self, c):
"""判断阳线"""
return float(c['close']) > float(c['open'])
def is_bearish(self, c):
"""判断阴线"""
return float(c['close']) < float(c['open'])
def get_body_size(self, candle):
"""计算K线实体大小绝对值"""
return abs(float(candle['open']) - float(candle['close']))
def find_valid_prev_bar(self, all_data, current_idx, min_body_size=0.1):
"""
从当前索引往前查找,直到找到实体>=min_body_size的K线
返回:(有效K线的索引, K线数据) 或 (None, None)
"""
if current_idx <= 0:
return None, None
for i in range(current_idx - 1, -1, -1):
prev = all_data[i]
body_size = self.get_body_size(prev)
if body_size >= min_body_size:
return i, prev
return None, None
def get_one_third_levels(self, prev):
"""
计算前一根K线实体的 1/3 双向触发价格
返回:(做多触发价格, 做空触发价格)
基于收盘价计算(无论阴线阳线):
- 做多触发价格 = 收盘价 + 实体/3从收盘价往上涨1/3实体
- 做空触发价格 = 收盘价 - 实体/3从收盘价往下跌1/3实体
示例:
阳线 open=3000, close=3100, 实体=100
- 做多触发 = 3100 + 33 = 3133继续涨
- 做空触发 = 3100 - 33 = 3067回调
阴线 open=3100, close=3000, 实体=100
- 做多触发 = 3000 + 33 = 3033反弹
- 做空触发 = 3000 - 33 = 2967继续跌
"""
p_open = float(prev['open'])
p_close = float(prev['close'])
body = abs(p_open - p_close)
if body < 0.001: # 十字星,忽略
return None, None
# 基于收盘价的双向触发价格
long_trigger = p_close + body / 3 # 从收盘价往上涨1/3触发做多
short_trigger = p_close - body / 3 # 从收盘价往下跌1/3触发做空
return long_trigger, short_trigger
def check_trigger(self, all_data, current_idx):
"""
检查当前K线是否触发了交易信号双向检测
返回:(方向, 触发价格, 有效前一根K线索引) 或 (None, None, None)
规则:
- 当前K线高点 >= 做多触发价格 → 做多信号
- 当前K线低点 <= 做空触发价格 → 做空信号
"""
if current_idx <= 0:
return None, None, None
curr = all_data[current_idx]
# 查找实体>=min_body_size的前一根K线
valid_prev_idx, prev = self.find_valid_prev_bar(all_data, current_idx, self.min_body_size)
if prev is None:
return None, None, None
long_trigger, short_trigger = self.get_one_third_levels(prev)
if long_trigger is None:
return None, None, None
# 使用影线部分high/low来判断
c_high = float(curr['high'])
c_low = float(curr['low'])
c_close = float(curr['close'])
p_close = float(prev['close'])
# 检测是否触发
long_triggered = c_high >= long_trigger
short_triggered = c_low <= short_trigger
# 当前价格相对前一根收盘的方向:已在前一根之上偏多,之下偏空
if long_triggered and short_triggered:
# 两个方向都触达时,以当前收盘相对前一根收盘为准,不按“谁先触达”
if c_close > p_close:
return 'long', long_trigger, valid_prev_idx
elif c_close < p_close:
return 'short', short_trigger, valid_prev_idx
c_open = float(curr['open'])
dist_to_long = abs(long_trigger - c_open)
dist_to_short = abs(short_trigger - c_open)
if dist_to_short <= dist_to_long:
return 'short', short_trigger, valid_prev_idx
return 'long', long_trigger, valid_prev_idx
if short_triggered:
# 仅触达做空价:若当前收盘已在前一根之上,说明已拉回偏多,不开空
if c_close > p_close:
return None, None, None
return 'short', short_trigger, valid_prev_idx
if long_triggered:
# 仅触达做多价:若当前收盘已在前一根之下,说明已回落偏空,不开多
if c_close < p_close:
return None, None, None
return 'long', long_trigger, valid_prev_idx
return None, None, None
def check_realtime_trigger(self, kline_data):
"""
实时检测当前K线是否触发信号双向检测
基于已收盘的K线计算触发价格用当前正在形成的K线判断
返回:(方向, 触发价格, 有效前一根K线, 当前K线) 或 (None, None, None, None)
"""
if len(kline_data) < 2:
return None, None, None, None
# 当前正在形成的K线最后一根未收盘
curr = kline_data[-1]
curr_kline_id = curr['id']
# 从倒数第二根开始往前找有效K线已收盘的K线
valid_prev_idx, prev = self.find_valid_prev_bar(kline_data, len(kline_data) - 1, self.min_body_size)
if prev is None:
return None, None, None, None
long_trigger, short_trigger = self.get_one_third_levels(prev)
if long_trigger is None:
return None, None, None, None
# 使用当前K线的实时高低点来判断
c_high = float(curr['high'])
c_low = float(curr['low'])
c_close = float(curr['close'])
p_close = float(prev['close'])
# 检测是否触发
long_triggered = c_high >= long_trigger
short_triggered = c_low <= short_trigger
# 确定触发方向:当前价格已在前一根之上偏多、之下偏空时,以当前方向为准
direction = None
trigger_price = None
if long_triggered and short_triggered:
# 两个方向都触达时,以当前收盘相对前一根收盘为准(不按谁先触达)
if c_close > p_close:
direction = 'long'
trigger_price = long_trigger
elif c_close < p_close:
direction = 'short'
trigger_price = short_trigger
else:
c_open = float(curr['open'])
dist_to_long = abs(long_trigger - c_open)
dist_to_short = abs(short_trigger - c_open)
if dist_to_short <= dist_to_long:
direction = 'short'
trigger_price = short_trigger
else:
direction = 'long'
trigger_price = long_trigger
elif short_triggered:
# 仅触达做空价:若当前收盘已在前一根之上,说明已拉回偏多,不开空
if c_close <= p_close:
direction = 'short'
trigger_price = short_trigger
elif long_triggered:
# 仅触达做多价:若当前收盘已在前一根之下,说明已回落偏空,不开多
if c_close >= p_close:
direction = 'long'
trigger_price = long_trigger
if direction is None:
return None, None, None, None
# 检查是否在同一根K线内已经触发过相同方向
if self.last_trigger_kline_id == curr_kline_id and self.last_trigger_direction == direction:
return None, None, None, None
return direction, trigger_price, prev, curr
# ========================= BitMart API 函数 =========================
def get_klines(self):
"""获取最近N根5分钟K线"""
try:
end_time = int(time.time())
# 获取足够多的K线用于向前查找有效K线
response = self.contractAPI.get_kline(
contract_symbol=self.contract_symbol,
step=self.kline_step, # 5分钟
start_time=end_time - 3600 * 3, # 取最近3小时
end_time=end_time
)[0]["data"]
# 每根: [timestamp, open, high, low, close, volume]
formatted = []
for k in response:
formatted.append({
'id': int(k["timestamp"]),
'open': float(k["open_price"]),
'high': float(k["high_price"]),
'low': float(k["low_price"]),
'close': float(k["close_price"])
})
formatted.sort(key=lambda x: x['id'])
return formatted
except Exception as e:
error_msg = str(e)
# 检查是否是429限流错误
if "429" in error_msg or "too many requests" in error_msg.lower():
logger.warning(f"API限流等待60秒后重试: {e}")
time.sleep(60)
else:
logger.error(f"获取K线异常: {e}")
self.ding(msg="获取K线异常", error=True)
return None
def get_current_price(self):
"""获取当前最新价格"""
try:
end_time = int(time.time())
response = self.contractAPI.get_kline(
contract_symbol=self.contract_symbol,
step=1, # 1分钟
start_time=end_time - 3600 * 3,
end_time=end_time
)[0]
if response['code'] == 1000:
return float(response['data'][-1]["close_price"])
return None
except Exception as e:
logger.error(f"获取价格异常: {e}")
return None
def get_available_balance(self):
"""获取合约账户可用USDT余额"""
try:
response = self.contractAPI.get_assets_detail()[0]
if response['code'] == 1000:
data = response['data']
if isinstance(data, dict):
return float(data.get('available_balance', 0))
elif isinstance(data, list):
for asset in data:
if asset.get('currency') == 'USDT':
return float(asset.get('available_balance', 0))
return None
except Exception as e:
logger.error(f"余额查询异常: {e}")
return None
def get_position_status(self):
"""获取当前持仓方向"""
try:
response = self.contractAPI.get_position(contract_symbol=self.contract_symbol)[0]
if response['code'] == 1000:
positions = response['data']
if not positions:
self.start = 0
self.open_avg_price = None
self.current_amount = None
self.position_cross = None
return True
self.start = 1 if positions[0]['position_type'] == 1 else -1
self.open_avg_price = positions[0]['open_avg_price']
self.current_amount = positions[0]['current_amount']
self.position_cross = positions[0]["position_cross"]
return True
else:
return False
except Exception as e:
logger.error(f"持仓查询异常: {e}")
return False
def set_leverage(self):
"""程序启动时设置全仓 + 高杠杆"""
try:
response = self.contractAPI.post_submit_leverage(
contract_symbol=self.contract_symbol,
leverage=self.leverage,
open_type=self.open_type
)[0]
if response['code'] == 1000:
logger.success(f"全仓模式 + {self.leverage}x 杠杆设置成功")
return True
else:
logger.error(f"杠杆设置失败: {response}")
return False
except Exception as e:
logger.error(f"设置杠杆异常: {e}")
return False
# ========================= 浏览器自动化函数 =========================
def openBrowser(self):
"""打开 TGE 对应浏览器实例"""
try:
bit_port = openBrowser(id=self.bit_id)
co = ChromiumOptions()
co.set_local_port(port=bit_port)
self.page = ChromiumPage(addr_or_opts=co)
return True
except:
return False
def close_extra_tabs_in_browser(self):
"""关闭多余 tab"""
try:
for idx, tab in enumerate(self.page.get_tabs()):
if idx > 0:
tab.close()
return True
except:
return False
def click_safe(self, xpath, sleep=0.5):
"""安全点击"""
try:
ele = self.page.ele(xpath)
if not ele:
return False
ele.scroll.to_see(center=True)
time.sleep(sleep)
ele.click(by_js=True)
return True
except:
return False
def 平仓(self):
"""市价平仓"""
logger.info("执行平仓操作...")
self.click_safe('x://span[normalize-space(text()) ="市价"]')
time.sleep(0.5)
self.ding(msg="执行平仓操作")
def 开单(self, marketPriceLongOrder=0, size=None):
"""
市价开单
marketPriceLongOrder: 1 做多, -1 做空
"""
if size is None or size <= 0:
logger.warning("开单金额无效")
return False
direction_str = "做多" if marketPriceLongOrder == 1 else "做空"
logger.info(f"执行{direction_str}操作,金额: {size}")
size = 50
try:
if marketPriceLongOrder == -1:
self.click_safe('x://button[normalize-space(text()) ="市价"]')
self.page.ele('x://*[@id="size_0"]').input(size)
self.click_safe('x://span[normalize-space(text()) ="卖出/做空"]')
elif marketPriceLongOrder == 1:
self.click_safe('x://button[normalize-space(text()) ="市价"]')
self.page.ele('x://*[@id="size_0"]').input(size)
self.click_safe('x://span[normalize-space(text()) ="买入/做多"]')
self.ding(msg=f"执行{direction_str}操作,金额: {size}")
return True
except Exception as e:
logger.error(f"开单异常: {e}")
return False
def ding(self, msg, error=False):
"""统一消息格式"""
prefix = "❌三分之一策略:" if error else "🔔三分之一策略:"
if error:
logger.error(msg)
for i in range(10):
send_dingtalk_message(f"{prefix}{msg}")
else:
logger.info(msg)
send_dingtalk_message(f"{prefix}{msg}")
# ========================= 时间计算函数 =========================
def get_now_time(self):
"""获取当前5分钟整点时间戳"""
current_timestamp = time.time()
current_datetime = datetime.datetime.fromtimestamp(current_timestamp)
# 计算距离当前时间最近的5分钟整点
minute = current_datetime.minute
target_minute = (minute // 5) * 5 # 向下取整到5分钟
target_datetime = current_datetime.replace(minute=target_minute, second=0, microsecond=0)
return int(target_datetime.timestamp())
def get_time_to_next_5min(self):
"""获取距离下一个5分钟的秒数"""
current_timestamp = time.time()
current_datetime = datetime.datetime.fromtimestamp(current_timestamp)
minute = current_datetime.minute
next_5min = ((minute // 5) + 1) * 5
if next_5min >= 60:
next_datetime = current_datetime.replace(minute=0, second=0, microsecond=0) + datetime.timedelta(hours=1)
else:
next_datetime = current_datetime.replace(minute=next_5min, second=0, microsecond=0)
return (next_datetime - current_datetime).total_seconds()
# ========================= 主运行函数 =========================
def action(self):
"""主运行逻辑 - 实时监测版本"""
# 启动时设置全仓高杠杆
if not self.set_leverage():
logger.error("杠杆设置失败,程序继续运行但可能下单失败")
return
# 1. 打开浏览器
if not self.openBrowser():
self.ding("打开浏览器失败!", error=True)
return
logger.info("浏览器打开成功")
if self.close_extra_tabs_in_browser():
logger.info('关闭多余标签页成功')
else:
logger.info('关闭多余标签页失败')
self.page.get("https://derivatives.bitmart.com/zh-CN/futures/ETHUSDT")
time.sleep(2)
self.click_safe('x://button[normalize-space(text()) ="市价"]')
logger.info(f"开始实时监测,检测间隔: {self.check_interval}")
# 用于定时发送持仓信息每5分钟发一次
last_report_time = 0
report_interval = 300 # 5分钟报告一次持仓
while True:
# 1. 打开浏览器
for i in range(5):
if self.openBrowser():
break
time.sleep(5)
else:
self.ding("打开浏览器失败!", error=True)
return
logger.info("浏览器打开成功")
if self.close_extra_tabs_in_browser():
logger.info('关闭多余标签页成功')
else:
logger.info('关闭多余标签页失败')
self.page.get("https://derivatives.bitmart.com/zh-CN/futures/ETHUSDT")
time.sleep(2)
self.click_safe('x://button[normalize-space(text()) ="市价"]')
try:
# 获取K线数据
kline_data = self.get_klines()
if not kline_data:
logger.warning("获取K线数据失败等待重试...")
time.sleep(self.check_interval)
continue
if len(kline_data) < 3:
logger.warning("K线数据不足")
time.sleep(self.check_interval)
continue
# 获取当前K线信息用于日志
curr = kline_data[-1]
curr_time_str = datetime.datetime.fromtimestamp(curr['id']).strftime('%H:%M:%S')
# ========== 实时信号检测 ==========
direction, trigger_price, valid_prev, curr_kline = self.check_realtime_trigger(kline_data)
if direction:
curr_kline_id = curr_kline['id']
# 获取持仓状态先获取用于判断是否允许同一K线内反手
if not self.get_position_status():
logger.warning("获取仓位信息失败")
time.sleep(self.check_interval)
continue
# 检查是否在同一K线内已经交易过防止频繁反手
# 例外同一根K线内仅允许一次反手
# - 先开空 -> 价格回调到做多触发价 -> 允许平空开多
# - 先开多 -> 价格跌到做空触发价 -> 允许平多开空
if self.last_trade_kline_id == curr_kline_id:
allow_reverse = (self.start == -1 and direction == "long") or (self.start == 1 and direction == "short")
if not allow_reverse:
logger.debug(f"同一K线内已交易且非反手场景跳过本次{direction}信号")
self.last_trigger_kline_id = curr_kline_id
self.last_trigger_direction = direction
time.sleep(self.check_interval)
continue
action_desc = "平空开多" if (self.start == -1 and direction == "long") else "平多开空"
logger.info(f"同一K线内回调/反弹触发反手:当前持仓{'' if self.start == -1 else ''},信号{direction} -> {action_desc}")
prev_time = datetime.datetime.fromtimestamp(valid_prev['id']).strftime('%H:%M')
prev_type = "阳线" if self.is_bullish(valid_prev) else "阴线"
prev_body = self.get_body_size(valid_prev)
# 检查信号与持仓是否同向(避免重复日志)
if (direction == "long" and self.start == 1) or (direction == "short" and self.start == -1):
# 信号与持仓同向,静默忽略
self.last_trigger_kline_id = curr_kline_id
self.last_trigger_direction = direction
time.sleep(self.check_interval)
continue
# 开仓原因(用于日志:多久、为什么开仓)
is_same_kline_reverse = (self.last_trade_kline_id == curr_kline_id)
if is_same_kline_reverse and direction == "long":
open_reason = f"同一根K线内价格回调到做多触发价 {trigger_price:.2f}(前一根[{prev_time}]{prev_type} 实体={prev_body:.2f}),平空反手开多"
elif is_same_kline_reverse and direction == "short":
open_reason = f"同一根K线内价格跌到做空触发价 {trigger_price:.2f}(前一根[{prev_time}]{prev_type} 实体={prev_body:.2f}),平多反手开空"
elif direction == "long":
open_reason = f"当前K线最高价触达做多触发价 {trigger_price:.2f}(前一根[{prev_time}]{prev_type} 实体={prev_body:.2f} 收盘={valid_prev['close']:.2f}"
else:
open_reason = f"当前K线最低价触达做空触发价 {trigger_price:.2f}(前一根[{prev_time}]{prev_type} 实体={prev_body:.2f} 收盘={valid_prev['close']:.2f}"
open_time_str = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
logger.info(f"{'=' * 50}")
logger.info(f"🚨 检测到{direction}信号!触发价格: {trigger_price:.2f}")
logger.info(
f" 有效前一根[{prev_time}]: {prev_type} 实体={prev_body:.2f} O={valid_prev['open']:.2f} C={valid_prev['close']:.2f}")
logger.info(
f" 当前K线: H={curr_kline['high']:.2f} L={curr_kline['low']:.2f} C={curr_kline['close']:.2f}")
logger.info(f" 当前持仓: {self.start} (1=多, -1=空, 0=无)")
logger.info(f" 开仓时间: {open_time_str}")
logger.info(f" 开仓原因: {open_reason}")
# ========== 执行交易逻辑 ==========
balance = self.get_available_balance()
if balance is None:
balance = 0
trade_size = balance * self.risk_percent
executed = False
if direction == "long":
if self.start == -1: # 当前空仓,平空开多
logger.info(f"📈 平空仓,反手开多 | {open_time_str} | {open_reason}")
self.平仓()
time.sleep(1)
self.开单(marketPriceLongOrder=1, size=trade_size)
executed = True
elif self.start == 0: # 当前无仓,直接开多
logger.info(f"📈 无仓位,开多 | {open_time_str} | {open_reason}")
self.开单(marketPriceLongOrder=1, size=trade_size)
executed = True
elif direction == "short":
if self.start == 1: # 当前多仓,平多开空
logger.info(f"📉 平多仓,反手开空 | {open_time_str} | {open_reason}")
self.平仓()
time.sleep(1)
self.开单(marketPriceLongOrder=-1, size=trade_size)
executed = True
elif self.start == 0: # 当前无仓,直接开空
logger.info(f"📉 无仓位,开空 | {open_time_str} | {open_reason}")
self.开单(marketPriceLongOrder=-1, size=trade_size)
executed = True
# 记录本次触发
self.last_trigger_kline_id = curr_kline_id
self.last_trigger_direction = direction
if executed:
# 记录交易K线防止同一K线内频繁反手
self.last_trade_kline_id = curr_kline_id
# 发送开仓时间与原因到钉钉
self.ding(msg=f"开仓时间: {open_time_str}\n开仓原因: {open_reason}")
# 交易后立即发送持仓信息
self.get_position_status()
self._send_position_message(curr_kline)
last_report_time = time.time()
logger.info(f"{'=' * 50}")
else:
# 没有信号时,显示实时价格
logger.debug(
f"[{curr_time_str}] 现价: {curr['close']:.2f} H={curr['high']:.2f} L={curr['low']:.2f}")
# ========== 定时发送持仓信息 ==========
current_time = time.time()
if current_time - last_report_time >= report_interval:
if self.get_position_status():
self._send_position_message(kline_data[-1])
last_report_time = current_time
# 等待下次检测
time.sleep(self.check_interval)
except Exception as e:
logger.error(f"主循环异常: {e}")
time.sleep(self.check_interval)
time.sleep(15)
self.page.close()
time.sleep(15)
def _send_position_message(self, latest_kline):
"""发送持仓信息到钉钉"""
current_price = float(latest_kline["close"])
balance = self.get_available_balance()
self.balance = balance if balance is not None else 0.0
if self.start != 0:
open_avg_price = float(self.open_avg_price) if self.open_avg_price else 0.0
current_amount = float(self.current_amount) if self.current_amount else 0.0
position_cross = float(self.position_cross) if hasattr(self,
'position_cross') and self.position_cross else 0.0
# 计算浮动盈亏
if self.start == 1: # 多头
unrealized_pnl = current_amount * 0.001 * (current_price - open_avg_price)
else: # 空头
unrealized_pnl = current_amount * 0.001 * (open_avg_price - current_price)
# 计算收益率
if open_avg_price > 0:
if self.start == 1:
pnl_rate = (current_price - open_avg_price) / open_avg_price * 10000
else:
pnl_rate = (open_avg_price - current_price) / open_avg_price * 10000
rate_str = f" ({pnl_rate:+.2f}%)"
else:
rate_str = ""
direction_str = "" if self.start == -1 else ""
pnl_str = f"{unrealized_pnl:+.2f} USDT"
msg = (
f"【三分之一策略 {self.contract_symbol} 5分钟】\n"
f"当前方向:{direction_str}\n"
f"当前现价:{current_price:.2f} USDT\n"
f"开仓均价:{open_avg_price:.2f} USDT\n"
f"持仓量(eth){float(current_amount) / 1000} eth\n"
f"持仓量(usdt){position_cross} usdt\n"
f"浮动盈亏:{pnl_str}{rate_str}\n"
f"账户可用余额:{self.balance:.2f} usdt"
)
else:
msg = (
f"【三分之一策略 {self.contract_symbol} 5分钟】\n"
f"当前方向:无\n"
f"当前现价:{current_price:.2f} USDT\n"
f"账户可用余额:{self.balance:.2f} usdt"
)
self.ding(msg=msg)
if __name__ == '__main__':
# 启动三分之一策略交易
BitmartOneThirdStrategy(bit_id="62f9107d0c674925972084e282df55b3").action()

View File

@@ -0,0 +1,715 @@
"""
BitMart 三分之一回归策略交易(双向触发版)
使用5分钟K线周期实时监测
策略规则:
1. 触发价格计算基于有效的前一根K线实体>=0.1
- 做多触发价格 = 收盘价 + 实体/3从收盘价往上涨1/3
- 做空触发价格 = 收盘价 - 实体/3从收盘价往下跌1/3
2. 信号触发条件:
- 当前K线最高价 >= 做多触发价格 → 做多信号
- 当前K线最低价 <= 做空触发价格 → 做空信号
3. 执行逻辑:
- 做多时遇到做空信号 -> 平多并反手开空
- 做空时遇到做多信号 -> 平空并反手开多
- 同一根K线内只交易一次防止频繁反手
示例1阳线
前一根K线开盘3000收盘3100阳线实体=100
- 做多触发价格 = 3100 + 33 = 3133继续上涨做多
- 做空触发价格 = 3100 - 33 = 3067回调做空←当前跌到这里就做空
示例2阴线
前一根K线开盘3100收盘3000阴线实体=100
- 做多触发价格 = 3000 + 33 = 3033反弹做多
- 做空触发价格 = 3000 - 33 = 2967继续下跌做空
"""
import time
import datetime
from tqdm import tqdm
from loguru import logger
from bit_tools import openBrowser
from DrissionPage import ChromiumPage
from DrissionPage import ChromiumOptions
from bitmart.api_contract import APIContract
from 交易.tools import send_dingtalk_message
class BitmartOneThirdStrategy:
def __init__(self, bit_id):
self.page: ChromiumPage | None = None
self.api_key = "6104088c65a68d7e53df5d9395b67d78e555293a"
self.secret_key = "a8b14312330d8e6b9b09acfd972b34e32022fdfa9f2b06f0a0a31723b873fd01"
self.memo = "me"
self.contract_symbol = "ETHUSDT"
self.contractAPI = APIContract(self.api_key, self.secret_key, self.memo, timeout=(5, 15))
self.start = 0 # 持仓状态: -1 空, 0 无, 1 多
self.direction = None
self.pbar = tqdm(total=5, desc="等待K线", ncols=80) # 5分钟周期
self.last_kline_time = None
self.leverage = "40" # 高杠杆(全仓模式下可开更大仓位)
self.open_type = "cross" # 全仓模式
self.risk_percent = 0.01 # 每次开仓使用可用余额的 1%
self.open_avg_price = None # 开仓价格
self.current_amount = None # 持仓量
self.bit_id = bit_id
# 三分之一策略参数
self.min_body_size = 0.1 # 最小实体大小
self.kline_step = 5 # K线周期5分钟
self.kline_count = 20 # 获取的K线数量用于向前查找有效K线
# 实时监测参数
self.check_interval = 3 # 检测间隔(秒)
self.last_trigger_kline_id = None # 记录上次触发信号的K线ID避免同一K线重复触发
self.last_trigger_direction = None # 记录上次触发的方向
self.last_trade_kline_id = None # 记录上次实际交易的K线ID防止同一K线内频繁反手
# ========================= 三分之一策略核心函数 =========================
def is_bullish(self, c):
"""判断阳线"""
return float(c['close']) > float(c['open'])
def is_bearish(self, c):
"""判断阴线"""
return float(c['close']) < float(c['open'])
def get_body_size(self, candle):
"""计算K线实体大小绝对值"""
return abs(float(candle['open']) - float(candle['close']))
def find_valid_prev_bar(self, all_data, current_idx, min_body_size=0.1):
"""
从当前索引往前查找,直到找到实体>=min_body_size的K线
返回:(有效K线的索引, K线数据) 或 (None, None)
"""
if current_idx <= 0:
return None, None
for i in range(current_idx - 1, -1, -1):
prev = all_data[i]
body_size = self.get_body_size(prev)
if body_size >= min_body_size:
return i, prev
return None, None
def get_one_third_levels(self, prev):
"""
计算前一根K线实体的 1/3 双向触发价格
返回:(做多触发价格, 做空触发价格)
基于收盘价计算(无论阴线阳线):
- 做多触发价格 = 收盘价 + 实体/3从收盘价往上涨1/3实体
- 做空触发价格 = 收盘价 - 实体/3从收盘价往下跌1/3实体
示例:
阳线 open=3000, close=3100, 实体=100
- 做多触发 = 3100 + 33 = 3133继续涨
- 做空触发 = 3100 - 33 = 3067回调
阴线 open=3100, close=3000, 实体=100
- 做多触发 = 3000 + 33 = 3033反弹
- 做空触发 = 3000 - 33 = 2967继续跌
"""
p_open = float(prev['open'])
p_close = float(prev['close'])
body = abs(p_open - p_close)
if body < 0.001: # 十字星,忽略
return None, None
# 基于收盘价的双向触发价格
long_trigger = p_close + body / 3 # 从收盘价往上涨1/3触发做多
short_trigger = p_close - body / 3 # 从收盘价往下跌1/3触发做空
return long_trigger, short_trigger
def check_trigger(self, all_data, current_idx):
"""
检查当前K线是否触发了交易信号双向检测
返回:(方向, 触发价格, 有效前一根K线索引) 或 (None, None, None)
规则:
- 当前K线高点 >= 做多触发价格 → 做多信号
- 当前K线低点 <= 做空触发价格 → 做空信号
"""
if current_idx <= 0:
return None, None, None
curr = all_data[current_idx]
# 查找实体>=min_body_size的前一根K线
valid_prev_idx, prev = self.find_valid_prev_bar(all_data, current_idx, self.min_body_size)
if prev is None:
return None, None, None
long_trigger, short_trigger = self.get_one_third_levels(prev)
if long_trigger is None:
return None, None, None
# 使用影线部分high/low来判断
c_high = float(curr['high'])
c_low = float(curr['low'])
# 检测是否触发
long_triggered = c_high >= long_trigger
short_triggered = c_low <= short_trigger
# 如果两个方向都触发,判断哪个先触发
if long_triggered and short_triggered:
c_open = float(curr['open'])
dist_to_long = abs(long_trigger - c_open)
dist_to_short = abs(short_trigger - c_open)
if dist_to_short <= dist_to_long:
return 'short', short_trigger, valid_prev_idx
else:
return 'long', long_trigger, valid_prev_idx
if short_triggered:
return 'short', short_trigger, valid_prev_idx
if long_triggered:
return 'long', long_trigger, valid_prev_idx
return None, None, None
def check_realtime_trigger(self, kline_data):
"""
实时检测当前K线是否触发信号双向检测
基于已收盘的K线计算触发价格用当前正在形成的K线判断
返回:(方向, 触发价格, 有效前一根K线, 当前K线) 或 (None, None, None, None)
"""
if len(kline_data) < 2:
return None, None, None, None
# 当前正在形成的K线最后一根未收盘
curr = kline_data[-1]
curr_kline_id = curr['id']
# 从倒数第二根开始往前找有效K线已收盘的K线
valid_prev_idx, prev = self.find_valid_prev_bar(kline_data, len(kline_data) - 1, self.min_body_size)
if prev is None:
return None, None, None, None
long_trigger, short_trigger = self.get_one_third_levels(prev)
if long_trigger is None:
return None, None, None, None
# 使用当前K线的实时高低点来判断
c_high = float(curr['high'])
c_low = float(curr['low'])
# 检测是否触发
long_triggered = c_high >= long_trigger
short_triggered = c_low <= short_trigger
# 确定触发方向
direction = None
trigger_price = None
if long_triggered and short_triggered:
# 两个方向都触发,判断哪个先(距离开盘价更近的先触发)
c_open = float(curr['open'])
dist_to_long = abs(long_trigger - c_open)
dist_to_short = abs(short_trigger - c_open)
if dist_to_short <= dist_to_long:
direction = 'short'
trigger_price = short_trigger
else:
direction = 'long'
trigger_price = long_trigger
elif short_triggered:
direction = 'short'
trigger_price = short_trigger
elif long_triggered:
direction = 'long'
trigger_price = long_trigger
if direction is None:
return None, None, None, None
# 检查是否在同一根K线内已经触发过相同方向
if self.last_trigger_kline_id == curr_kline_id and self.last_trigger_direction == direction:
return None, None, None, None
return direction, trigger_price, prev, curr
# ========================= BitMart API 函数 =========================
def get_klines(self):
"""获取最近N根5分钟K线"""
try:
end_time = int(time.time())
# 获取足够多的K线用于向前查找有效K线
response = self.contractAPI.get_kline(
contract_symbol=self.contract_symbol,
step=self.kline_step, # 5分钟
start_time=end_time - 3600 * 3, # 取最近3小时
end_time=end_time
)[0]["data"]
# 每根: [timestamp, open, high, low, close, volume]
formatted = []
for k in response:
formatted.append({
'id': int(k["timestamp"]),
'open': float(k["open_price"]),
'high': float(k["high_price"]),
'low': float(k["low_price"]),
'close': float(k["close_price"])
})
formatted.sort(key=lambda x: x['id'])
return formatted
except Exception as e:
error_msg = str(e)
# 检查是否是429限流错误
if "429" in error_msg or "too many requests" in error_msg.lower():
logger.warning(f"API限流等待60秒后重试: {e}")
time.sleep(60)
else:
logger.error(f"获取K线异常: {e}")
self.ding(msg="获取K线异常", error=True)
return None
def get_current_price(self):
"""获取当前最新价格"""
try:
end_time = int(time.time())
response = self.contractAPI.get_kline(
contract_symbol=self.contract_symbol,
step=1, # 1分钟
start_time=end_time - 3600 * 3,
end_time=end_time
)[0]
if response['code'] == 1000:
return float(response['data'][-1]["close_price"])
return None
except Exception as e:
logger.error(f"获取价格异常: {e}")
return None
def get_available_balance(self):
"""获取合约账户可用USDT余额"""
try:
response = self.contractAPI.get_assets_detail()[0]
if response['code'] == 1000:
data = response['data']
if isinstance(data, dict):
return float(data.get('available_balance', 0))
elif isinstance(data, list):
for asset in data:
if asset.get('currency') == 'USDT':
return float(asset.get('available_balance', 0))
return None
except Exception as e:
logger.error(f"余额查询异常: {e}")
return None
def get_position_status(self):
"""获取当前持仓方向"""
try:
response = self.contractAPI.get_position(contract_symbol=self.contract_symbol)[0]
if response['code'] == 1000:
positions = response['data']
if not positions:
self.start = 0
self.open_avg_price = None
self.current_amount = None
self.position_cross = None
return True
self.start = 1 if positions[0]['position_type'] == 1 else -1
self.open_avg_price = positions[0]['open_avg_price']
self.current_amount = positions[0]['current_amount']
self.position_cross = positions[0]["position_cross"]
return True
else:
return False
except Exception as e:
logger.error(f"持仓查询异常: {e}")
return False
def set_leverage(self):
"""程序启动时设置全仓 + 高杠杆"""
try:
response = self.contractAPI.post_submit_leverage(
contract_symbol=self.contract_symbol,
leverage=self.leverage,
open_type=self.open_type
)[0]
if response['code'] == 1000:
logger.success(f"全仓模式 + {self.leverage}x 杠杆设置成功")
return True
else:
logger.error(f"杠杆设置失败: {response}")
return False
except Exception as e:
logger.error(f"设置杠杆异常: {e}")
return False
# ========================= 浏览器自动化函数 =========================
def openBrowser(self):
"""打开 TGE 对应浏览器实例"""
try:
bit_port = openBrowser(id=self.bit_id)
co = ChromiumOptions()
co.set_local_port(port=bit_port)
self.page = ChromiumPage(addr_or_opts=co)
return True
except:
return False
def close_extra_tabs_in_browser(self):
"""关闭多余 tab"""
try:
for idx, tab in enumerate(self.page.get_tabs()):
if idx > 0:
tab.close()
return True
except:
return False
def click_safe(self, xpath, sleep=0.5):
"""安全点击"""
try:
ele = self.page.ele(xpath)
if not ele:
return False
ele.scroll.to_see(center=True)
time.sleep(sleep)
ele.click(by_js=True)
return True
except:
return False
def 平仓(self):
"""市价平仓"""
logger.info("执行平仓操作...")
self.click_safe('x://span[normalize-space(text()) ="市价"]')
time.sleep(0.5)
self.ding(msg="执行平仓操作")
def 开单(self, marketPriceLongOrder=0, size=None):
"""
市价开单
marketPriceLongOrder: 1 做多, -1 做空
"""
if size is None or size <= 0:
logger.warning("开单金额无效")
return False
direction_str = "做多" if marketPriceLongOrder == 1 else "做空"
logger.info(f"执行{direction_str}操作,金额: {size}")
size = 40
try:
if marketPriceLongOrder == -1:
self.click_safe('x://button[normalize-space(text()) ="市价"]')
self.page.ele('x://*[@id="size_0"]').input(size)
self.click_safe('x://span[normalize-space(text()) ="卖出/做空"]')
elif marketPriceLongOrder == 1:
self.click_safe('x://button[normalize-space(text()) ="市价"]')
self.page.ele('x://*[@id="size_0"]').input(size)
self.click_safe('x://span[normalize-space(text()) ="买入/做多"]')
self.ding(msg=f"执行{direction_str}操作,金额: {size}")
return True
except Exception as e:
logger.error(f"开单异常: {e}")
return False
def ding(self, msg, error=False):
"""统一消息格式"""
prefix = "❌三分之一策略:" if error else "🔔三分之一策略:"
if error:
logger.error(msg)
for i in range(10):
send_dingtalk_message(f"{prefix}{msg}")
else:
logger.info(msg)
send_dingtalk_message(f"{prefix}{msg}")
# ========================= 时间计算函数 =========================
def get_now_time(self):
"""获取当前5分钟整点时间戳"""
current_timestamp = time.time()
current_datetime = datetime.datetime.fromtimestamp(current_timestamp)
# 计算距离当前时间最近的5分钟整点
minute = current_datetime.minute
target_minute = (minute // 5) * 5 # 向下取整到5分钟
target_datetime = current_datetime.replace(minute=target_minute, second=0, microsecond=0)
return int(target_datetime.timestamp())
def get_time_to_next_5min(self):
"""获取距离下一个5分钟的秒数"""
current_timestamp = time.time()
current_datetime = datetime.datetime.fromtimestamp(current_timestamp)
minute = current_datetime.minute
next_5min = ((minute // 5) + 1) * 5
if next_5min >= 60:
next_datetime = current_datetime.replace(minute=0, second=0, microsecond=0) + datetime.timedelta(hours=1)
else:
next_datetime = current_datetime.replace(minute=next_5min, second=0, microsecond=0)
return (next_datetime - current_datetime).total_seconds()
# ========================= 主运行函数 =========================
def action(self):
"""主运行逻辑 - 实时监测版本"""
# 启动时设置全仓高杠杆
if not self.set_leverage():
logger.error("杠杆设置失败,程序继续运行但可能下单失败")
return
# 1. 打开浏览器
if not self.openBrowser():
self.ding("打开浏览器失败!", error=True)
return
logger.info("浏览器打开成功")
if self.close_extra_tabs_in_browser():
logger.info('关闭多余标签页成功')
else:
logger.info('关闭多余标签页失败')
self.page.get("https://derivatives.bitmart.com/zh-CN/futures/ETHUSDT")
time.sleep(2)
self.click_safe('x://button[normalize-space(text()) ="市价"]')
logger.info(f"开始实时监测,检测间隔: {self.check_interval}")
# 用于定时发送持仓信息每5分钟发一次
last_report_time = 0
report_interval = 300 # 5分钟报告一次持仓
while True:
# 1. 打开浏览器
for i in range(5):
if self.openBrowser():
break
time.sleep(5)
else:
self.ding("打开浏览器失败!", error=True)
return
logger.info("浏览器打开成功")
if self.close_extra_tabs_in_browser():
logger.info('关闭多余标签页成功')
else:
logger.info('关闭多余标签页失败')
self.page.get("https://derivatives.bitmart.com/zh-CN/futures/ETHUSDT")
time.sleep(2)
self.click_safe('x://button[normalize-space(text()) ="市价"]')
try:
# 获取K线数据
kline_data = self.get_klines()
if not kline_data:
logger.warning("获取K线数据失败等待重试...")
time.sleep(self.check_interval)
continue
if len(kline_data) < 3:
logger.warning("K线数据不足")
time.sleep(self.check_interval)
continue
# 获取当前K线信息用于日志
curr = kline_data[-1]
curr_time_str = datetime.datetime.fromtimestamp(curr['id']).strftime('%H:%M:%S')
# ========== 实时信号检测 ==========
direction, trigger_price, valid_prev, curr_kline = self.check_realtime_trigger(kline_data)
if direction:
curr_kline_id = curr_kline['id']
# 检查是否在同一K线内已经交易过防止频繁反手
if self.last_trade_kline_id == curr_kline_id:
logger.debug(f"同一K线内已交易跳过本次{direction}信号")
# 更新触发记录,避免重复日志
self.last_trigger_kline_id = curr_kline_id
self.last_trigger_direction = direction
time.sleep(self.check_interval)
continue
# 获取持仓状态
if not self.get_position_status():
logger.warning("获取仓位信息失败")
time.sleep(self.check_interval)
continue
prev_time = datetime.datetime.fromtimestamp(valid_prev['id']).strftime('%H:%M')
prev_type = "阳线" if self.is_bullish(valid_prev) else "阴线"
prev_body = self.get_body_size(valid_prev)
# 检查信号与持仓是否同向(避免重复日志)
if (direction == "long" and self.start == 1) or (direction == "short" and self.start == -1):
# 信号与持仓同向,静默忽略
self.last_trigger_kline_id = curr_kline_id
self.last_trigger_direction = direction
time.sleep(self.check_interval)
continue
logger.info(f"{'=' * 50}")
logger.info(f"🚨 检测到{direction}信号!触发价格: {trigger_price:.2f}")
logger.info(
f" 有效前一根[{prev_time}]: {prev_type} 实体={prev_body:.2f} O={valid_prev['open']:.2f} C={valid_prev['close']:.2f}")
logger.info(
f" 当前K线: 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()
if balance is None:
balance = 0
trade_size = balance * self.risk_percent
executed = False
if direction == "long":
if self.start == -1: # 当前空仓,平空开多
logger.info("📈 平空仓,反手开多")
self.平仓()
time.sleep(1)
self.开单(marketPriceLongOrder=1, size=trade_size)
executed = True
elif self.start == 0: # 当前无仓,直接开多
logger.info("📈 无仓位,开多")
self.开单(marketPriceLongOrder=1, size=trade_size)
executed = True
elif direction == "short":
if self.start == 1: # 当前多仓,平多开空
logger.info("📉 平多仓,反手开空")
self.平仓()
time.sleep(1)
self.开单(marketPriceLongOrder=-1, size=trade_size)
executed = True
elif self.start == 0: # 当前无仓,直接开空
logger.info("📉 无仓位,开空")
self.开单(marketPriceLongOrder=-1, size=trade_size)
executed = True
# 记录本次触发
self.last_trigger_kline_id = curr_kline_id
self.last_trigger_direction = direction
if executed:
# 记录交易K线防止同一K线内频繁反手
self.last_trade_kline_id = curr_kline_id
# 交易后立即发送持仓信息
self.get_position_status()
self._send_position_message(curr_kline)
last_report_time = time.time()
logger.info(f"{'=' * 50}")
else:
# 没有信号时,显示实时价格
logger.debug(
f"[{curr_time_str}] 现价: {curr['close']:.2f} H={curr['high']:.2f} L={curr['low']:.2f}")
# ========== 定时发送持仓信息 ==========
current_time = time.time()
if current_time - last_report_time >= report_interval:
if self.get_position_status():
self._send_position_message(kline_data[-1])
last_report_time = current_time
# 等待下次检测
time.sleep(self.check_interval)
except Exception as e:
logger.error(f"主循环异常: {e}")
time.sleep(self.check_interval)
time.sleep(15)
self.page.close()
time.sleep(15)
def _send_position_message(self, latest_kline):
"""发送持仓信息到钉钉"""
current_price = float(latest_kline["close"])
balance = self.get_available_balance()
self.balance = balance if balance is not None else 0.0
if self.start != 0:
open_avg_price = float(self.open_avg_price) if self.open_avg_price else 0.0
current_amount = float(self.current_amount) if self.current_amount else 0.0
position_cross = float(self.position_cross) if hasattr(self,
'position_cross') and self.position_cross else 0.0
# 计算浮动盈亏
if self.start == 1: # 多头
unrealized_pnl = current_amount * 0.001 * (current_price - open_avg_price)
else: # 空头
unrealized_pnl = current_amount * 0.001 * (open_avg_price - current_price)
# 计算收益率
if open_avg_price > 0:
if self.start == 1:
pnl_rate = (current_price - open_avg_price) / open_avg_price * 10000
else:
pnl_rate = (open_avg_price - current_price) / open_avg_price * 10000
rate_str = f" ({pnl_rate:+.2f}%)"
else:
rate_str = ""
direction_str = "" if self.start == -1 else ""
pnl_str = f"{unrealized_pnl:+.2f} USDT"
msg = (
f"【三分之一策略 {self.contract_symbol} 5分钟】\n"
f"当前方向:{direction_str}\n"
f"当前现价:{current_price:.2f} USDT\n"
f"开仓均价:{open_avg_price:.2f} USDT\n"
f"持仓量(eth){float(current_amount) / 1000} eth\n"
f"持仓量(usdt){position_cross} usdt\n"
f"浮动盈亏:{pnl_str}{rate_str}\n"
f"账户可用余额:{self.balance:.2f} usdt"
)
else:
msg = (
f"【三分之一策略 {self.contract_symbol} 5分钟】\n"
f"当前方向:无\n"
f"当前现价:{current_price:.2f} USDT\n"
f"账户可用余额:{self.balance:.2f} usdt"
)
self.ding(msg=msg)
if __name__ == '__main__':
# 启动三分之一策略交易
BitmartOneThirdStrategy(bit_id="62f9107d0c674925972084e282df55b3").action()