import csv from datetime import datetime, timezone import matplotlib.pyplot as plt # ---------------- 配置 ---------------- CSV_FILE = "bitmart/kline_3.csv" # 你的 CSV 文件路径 LEVERAGE = 100 CAPITAL = 10000 POSITION_RATIO = 0.01 FEE_RATE = 0.00015 # ---------------- 读取 CSV ---------------- data = [] with open(CSV_FILE, 'r') as f: reader = csv.DictReader(f) for row in reader: ts = int(row['id']) dt = datetime.fromtimestamp(ts, tz=timezone.utc) if dt.year == 2025 and dt.month == 1: data.append({ 'time': dt, 'open': float(row['open']), 'high': float(row['high']), 'low': float(row['low']), 'close': float(row['close']), }) # ---------------- 识别交易信号 ---------------- trades = [] position_usdt = CAPITAL * POSITION_RATIO leveraged_position = position_usdt * LEVERAGE for i in range(len(data)-1): k1 = data[i] k2 = data[i+1] # 刺透形态(Piercing Line,多头) if k1['close'] < k1['open'] and k2['close'] > k2['open']: midpoint = (k1['open'] + k1['close']) / 2 if k2['open'] < k1['close'] and k2['close'] > midpoint: trades.append({ '方向': '多', '开仓时间': k2['time'], '开仓价格': k2['open'], '平仓时间': k2['time'], '平仓价格': k2['close'] }) # 乌云盖顶(Dark Cloud Cover,空头) elif k1['close'] > k1['open'] and k2['close'] < k2['open']: midpoint = (k1['open'] + k1['close']) / 2 if k2['open'] > k1['close'] and k2['close'] < midpoint: trades.append({ '方向': '空', '开仓时间': k2['time'], '开仓价格': k2['open'], '平仓时间': k2['time'], '平仓价格': k2['close'] }) # ---------------- 绘制 K 线图 ---------------- plt.figure(figsize=(16,6)) times = [k['time'] for k in data] opens = [k['open'] for k in data] closes = [k['close'] for k in data] highs = [k['high'] for k in data] lows = [k['low'] for k in data] # 绘制 K 线(用竖线表示最高最低价,用矩形表示开收盘价) for i in range(len(data)): color = 'green' if closes[i] >= opens[i] else 'red' plt.plot([times[i], times[i]], [lows[i], highs[i]], color='black') # 高低价 plt.plot([times[i]-0.0005, times[i]+0.0005], [opens[i], opens[i]], color=color, linewidth=5) # 开盘价 plt.plot([times[i]-0.0005, times[i]+0.0005], [closes[i], closes[i]], color=color, linewidth=5) # 收盘价 # ---------------- 标注交易信号 ---------------- for t in trades: if t['方向'] == '多': plt.scatter(t['开仓时间'], t['开仓价格'], color='green', marker='^', s=100, label='多开' if '多开' not in plt.gca().get_legend_handles_labels()[1] else "") plt.scatter(t['平仓时间'], t['平仓价格'], color='red', marker='v', s=100, label='多平' if '多平' not in plt.gca().get_legend_handles_labels()[1] else "") else: plt.scatter(t['开仓时间'], t['开仓价格'], color='red', marker='v', s=100, label='空开' if '空开' not in plt.gca().get_legend_handles_labels()[1] else "") plt.scatter(t['平仓时间'], t['平仓价格'], color='green', marker='^', s=100, label='空平' if '空平' not in plt.gca().get_legend_handles_labels()[1] else "") plt.xlabel('时间') plt.ylabel('价格(USDT)') plt.title('ETH 永续合约 1 月交易回测(刺透 & 乌云形态)') plt.legend() plt.grid(True) plt.gcf().autofmt_xdate() plt.show()