写了个交易机器人:双均线策略的实盘记录

为什么写交易机器人 做量化交易的人大概都有类似的想法:K 线不用一直盯着,让机器来执行策略,人在旁边看着就好。这样既不会被情绪左右,也不用天天坐在屏幕前。 这个想法本身没有问题,但实盘跑起来之后,你会发现很多细节是回测时根本想不到的。这篇文章主要记录我用 Python + CCXT 写的一个 OKX 合约交易机器人,从策略设计到部署上线的完整过程,希望能给同样在尝试的朋友一些参考。 策略选择 选了一个最简单的趋势跟踪策略:双均线交叉。 均线的逻辑很直观——短期均线(MA5)代表最近的价格趋势,长期均线(MA20)代表较长时间的趋势。当短期线上穿长期线时(金叉),意味着趋势可能向上,开多。当短期线下穿长期线时(死叉),趋势可能转弱,平多或开空。 这个策略的好处是容易理解,也容易执行。坏处是它在震荡行情里表现很差——价格反复穿越均线,频繁开平仓,手续费吃掉大部分利润。 核心代码逻辑 策略循环的核心逻辑大概是这样的: import ccxt import pandas as pd import time from datetime import datetime exchange = ccxt.okx({ 'apiKey': 'YOUR_API_KEY', 'secret': 'YOUR_SECRET_KEY', 'password': 'YOUR_API_PASSPHRASE', 'enableRateLimit': True, }) symbol = 'BTC-USDT-SWAP' timeframe = '1m' limit = 50 position_size = 50 # USDT leverage = 3 def get_ma_crossover(): """获取最新两根K线,计算MA5和MA20,判断是否金叉/死叉""" ohlcv = exchange.fetch_ohlcv(symbol, timeframe, limit=limit) df = pd.DataFrame(ohlcv, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume']) df['ma5'] = df['close'].rolling(window=5).mean() df['ma20'] = df['close'].rolling(window=20).mean() # 获取倒数第二根(上一根已收盘的K线)和倒数第三根的金叉状态 prev_ma5 = df['ma5'].iloc[-3] prev_ma20 = df['ma20'].iloc[-3] curr_ma5 = df['ma5'].iloc[-2] curr_ma20 = df['ma20'].iloc[-2] # 金叉:之前MA5 <= MA20,现在MA5 > MA20 golden_cross = prev_ma5 <= prev_ma20 and curr_ma5 > curr_ma20 # 死叉:之前MA5 >= MA20,现在MA5 < MA20 death_cross = prev_ma5 >= prev_ma20 and curr_ma5 < curr_ma20 return golden_cross, death_cross def get_position(): """查询当前持仓""" positions = exchange.fetch_positions([symbol]) for pos in positions: if pos['symbol'] == symbol and float(pos['contracts']) > 0: return pos return None def place_order(side, amount): """下单,带止盈止损""" # 先设置杠杆 exchange.set_leverage(leverage, symbol) # 开仓 order = exchange.create_market_order( symbol, side, amount, params={'leverage': leverage} ) # 获取开仓均价,设置止盈止损 # 这里需要根据实际成交价来设置 # 实际项目中会从 order 或后续查询中获取 fill price print(f"{datetime.now()} | {'多头' if side == 'buy' else '空头'}开仓 | 数量: {amount}") return order def main_loop(): """主循环""" print(f"策略启动: {symbol} | 时间周期: {timeframe} | 杠杆: {leverage}x") while True: try: golden, death = get_ma_crossover() position = get_position() if golden and not position: # 金叉且无持仓 → 开多 place_order('buy', position_size) elif death and position: # 死叉且有持仓 → 平多(可改为开空,根据策略偏好) exchange.create_market_order(symbol, 'sell', position['contracts']) print(f"{datetime.now()} | 平仓") time.sleep(10) # 每10秒检查一次 except Exception as e: print(f"错误: {e}") time.sleep(30) if __name__ == '__main__': main_loop() 实际项目中还需要处理很多边界情况:API 限频、网络断开重连、订单未完全成交、止盈止损的挂单管理等等。下面会详细说。 ...

2026-05-23 · 4 min · 761 words · Seb