我设置的5分钟的macd大于0的情况下,1分钟的kdj的j线上穿0,下多单。5分钟的macd小于0的情况下,1分钟的kdj的j线下穿100,下空单。5点止损,5点以上利润减少40%就平所有仓位,有仓位时不开新单。但是回测不出结果,不知道问题出在哪里了。求解答。
from PythonApi import *
import pandas as pd import numpy as np def init(context): context.position = 0 # 1 for long, -1 for short, 0 for no position context.entry_price = 0 context.stop_loss = 0 context.max_profit = 0 context.trail_profit = 0 context.mindiff = get_instruments(context.run_info.base_book_id).mintick def convert_ndarray_to_dataframe(data, columns): df = pd.DataFrame(data, columns=columns) return df def calculate_macd(data, short_period=12, long_period=26, signal_period=9): short_ema = data["close"].ewm(span=short_period, adjust=False).mean() long_ema = data["close"].ewm(span=long_period, adjust=False).mean() macd = short_ema - long_ema signal = macd.ewm(span=signal_period, adjust=False).mean() return macd, signal def calculate_kdj(data, n=9, k_period=3, d_period=3): low_min = data["low"].rolling(window=n, min_periods=1).min() high_max = data["high"].rolling(window=n, min_periods=1).max() rsv = (data["close"] - low_min) / (high_max - low_min) * 100 k = rsv.ewm(com=(k_period - 1), min_periods=1).mean() d = k.ewm(com=(d_period - 1), min_periods=1).mean() j = 3 * k - 2 * d data["K"] = k data["D"] = d data["J"] = j return data def handle_bar(context): security = context.run_info.base_book_id # 获取当前交易的证券代码 # 获取1分钟和5分钟历史数据 data_1m_raw = history_bars(security, 30, "1m", ["close", "high", "low"]) data_5m_raw = history_bars( security, 31, "5m", ["close"] ) # 获取31条数据,用于计算前一根完整的5分钟数据 # 确保数据量足够 if len(data_1m_raw) < 30 or len(data_5m_raw) < 31: return # 将ndarray转换为DataFrame data_1m = convert_ndarray_to_dataframe(data_1m_raw, ["close", "high", "low"]) data_5m = convert_ndarray_to_dataframe( data_5m_raw[:-1], ["close"] ) # 使用前30条数据 # 计算MACD和KDJ指标 macd_5m, signal_5m = calculate_macd(data_5m) data_1m = calculate_kdj(data_1m) # 当前价格 current_price = data_1m["close"].iloc[-1] # 判断是否有未平仓订单 if context.position != 0: max_profit = max( context.max_profit, ( current_price - context.entry_price if context.position == 1 else context.entry_price - current_price ), ) trail_profit = ( context.entry_price + 1 * context.mindiff if context.position == 1 else context.entry_price - 1 * context.mindiff ) if ( context.position == 1 and ( current_price < context.stop_loss or ( max_profit >= 5 * context.mindiff and current_price < context.entry_price + max_profit * 0.6 ) ) ) or ( context.position == -1 and ( current_price > context.stop_loss or ( max_profit >= 5 * context.mindiff and current_price > context.entry_price - max_profit * 0.6 ) ) ): if context.position == 1: sell_close(security, "Market", volume=100) print(f"Sell at {current_price} on {security}") else: buy_close(security, "Market", volume=100) print(f"Cover at {current_price} on {security}") context.position = 0 # 没有未平仓订单时判断开仓信号 if context.position == 0: if macd_5m.iloc[-1] > signal_5m.iloc[-1]: if data_1m["J"].iloc[-2] < 0 and data_1m["J"].iloc[-1] > 0: buy_open(security, "Market", volume=100) context.position = 1 context.entry_price = current_price context.stop_loss = current_price - 5 * context.mindiff context.max_profit = 0 print(f"Buy at {current_price} on {security}") elif macd_5m.iloc[-1] < signal_5m.iloc[-1]: if data_1m["J"].iloc[-2] > 100 and data_1m["J"].iloc[-1] < 100: sell_open(security, "Market", volume=100) context.position = -1 context.entry_price = current_price context.stop_loss = current_price + 5 * context.mindiff context.max_profit = 0 print(f"Short at {current_price} on {security}") |