

它并非单纯“看红买、见绿卖”的粗放操作,而是结合均线系统、震荡指标构建的标准化交易体系,尤其适合A股市场的波段行情。本文将从策略核心逻辑、Python代码落地、批量回测验证、实战技巧优化四个维度,手把手教你掌握红买绿停交易技巧,实现从“人工看盘”到“量化实战”的跨越。




红买绿停策略的核心的是“趋势定位+信号过滤”,通过均线系统界定价格区间,结合震荡指标辅助判断,最终生成“红买、绿停、黄观望”三大交易信号,其底层逻辑完全复刻通达信经典公式,确保信号的一致性和可靠性。

核心公式解析(原文复刻)


X_1:=35;
X_2:=35;
X_3:=3;
X_4:=MA(CLOSE,5);
X_5:=MA(CLOSE,10);
X_6:=MA(CLOSE,20);
X_7:=(HHV(HIGH,X_1)-CLOSE)/(HHV(HIGH,X_1)-LLV(LOW,X_1))*100-X_2;
X_8:=SMA(X_7,X_1,1)+100;
X_9:=(CLOSE-LLV(LOW,X_1))/(HHV(HIGH,X_1)-LLV(LOW,X_1))*100;
X_10:=SMA(X_9,3,1);
X_11:=SMA(X_10,3,1)+100;
X_12:=X_11-X_8;
X_13:=IF(X_12>X_3,X_12-X_3,0)*2.5;
X_14:=100;
X_15:=BARSLASTCOUNT(X_13 AND X_13>100)=1;
X_16:=MAX(MA(CLOSE,13),MA(CLOSE,34));
X_17:=MIN(MA(CLOSE,13),MA(CLOSE,34));
红买:CLOSE<X_17,COLORRED;
绿停:CLOSE>X_16,COLORGREEN;
黄观望:X_16>=CLOSE AND CLOSE>=X_17,COLORYELLOW;
STICKLINE(CLOSE>X_16,0,2,8,0),COLORRED,LINETHICK2;
STICKLINE(CLOSE<X_17,0,2,8,0),COLOR008800,LINETHICK2;
STICKLINE(X_16>=CLOSE AND CLOSE>=X_17,0,2,8,0),COLORYELLOW,LINETHICK2;
STICKLINE(CLOSE>X_16 AND X_15,2,3,4,0),COLORMAGENTA,LINETHICK2;


信号逻辑拆解(通俗易懂)



核心均线:13日均线+34日均线:这是策略的“趋势锚点”,X_16是13日和34日均线的最大值,X_17是两者的最小值,两条均线形成一个“价格区间”,界定趋势方向。




红买信号(买入):当收盘价跌破X_17(两条均线的最小值),说明价格处于趋势低位,触发买入信号,对应公式中的“CLOSE<X_17”,用红色标记。




绿停信号(卖出/空仓):当收盘价突破X_16(两条均线的最大值),说明价格处于趋势高位,触发卖出或空仓信号,对应公式中的“CLOSE>X_16”,用绿色标记。




黄观望信号(持有/等待):当收盘价在X_16和X_17之间,说明趋势不明朗,此时不操作,持有现有仓位或等待信号明确,用黄色标记。



策略优势与适用场景



适用市场:A股主板、创业板、科创板(不适用于港股、美股,因交易规则差异);




适用行情:震荡市、波段趋势市(避开极端单边牛市/熊市,单边行情可结合其他指标优化);




适用人群:量化新手、波段交易者(无需盯盘,信号明确,可自动化执行)。





环境准备与依赖安装


pip install pandas numpy matplotlib tqdm struct

pandas:数据处理(生成DataFrame、计算均线);
numpy:数值计算(处理信号逻辑);
matplotlib:可视化(绘制K线、信号、均线);
struct:解析通达信.day二进制文件(A股本地数据核心);
tqdm:显示进度条(批量回测时更直观)。

核心代码落地(分步骤实现)



通达信的.day文件是二进制格式,存储了股票的日线数据(开盘价、收盘价、最高价、最低价等),通常位于通达信安装目录的“vipdoc\sz\lday”(深圳)和“vipdoc\sh\lday”(上海)文件夹下,文件命名格式为“sh600000.day”“sz000001.day”。


import osimport pandas as pdimport numpy as npimport structimport matplotlib.pyplot as pltfrom tqdm import tqdm# 解析通达信.day文件(核心函数)def parse_tdx_day(file_path):"""解析通达信二进制.day文件,返回K线DataFrame参数:file_path: .day文件路径返回:包含日期、开盘价、最高价、最低价、收盘价、成交量、成交额的DataFrame"""try:with open(file_path, 'rb') as f:buffer = f.read()# 通达信.day格式:每32字节一条数据,包含8个字段data_num = len(buffer) // 32 # 计算数据条数k_list = []for i in range(data_num):off = i * 32# 解包二进制数据,对应字段:日期、开盘价、最高价、最低价、收盘价、成交额、成交量、保留字段date, open_, high, low, close, amount, volume, _ = struct.unpack('IIIIIfII', buffer[off:off+32])# 处理数据格式:日期转为datetime,价格/成交量除以对应系数(通达信存储格式)k_list.append([pd.to_datetime(str(date)), # 日期:YYYYMMDD转为datetimeopen_/100, # 开盘价:通达信存储为整数,需除以100high/100, # 最高价:除以100low/100, # 最低价:除以100close/100, # 收盘价:除以100volume, # 成交量amount # 成交额])# 构建DataFrame并设置索引df = pd.DataFrame(k_list, columns=['date', 'open', 'high', 'low', 'close', 'volume', 'amount'])df.set_index('date', inplace=True)df.dropna(inplace=True)return df if len(df) > 60 else None # 过滤数据不足60天的股票(确保均线计算有效)except Exception as e:print(f"解析文件{file_path}失败:{e}")return None
class RedGreenStrategy:def __init__(self, X1=35, X2=35, X3=3):# 策略参数(对应通达信公式中的X_1~X_3,可自定义调整)self.X1 = X1 # HHV/LLV的周期self.X2 = X2 # X_7的偏移值self.X3 = X3 # X_13的阈值def calculate_signals(self, df):"""计算红买、绿停、黄观望信号参数:df: 股票K线DataFrame(包含open、high、low、close等字段)返回:添加了信号的DataFrame"""data = df.copy()close = data['close']high = data['high']low = data['low']# 1. 计算基础均线(对应公式X_4~X_6、X_16~X_17)data['ma5'] = close.rolling(5).mean() # X_4: 5日均线data['ma10'] = close.rolling(10).mean() # X_5: 10日均线data['ma20'] = close.rolling(20).mean() # X_6: 20日均线data['ma13'] = close.rolling(13).mean() # 13日均线data['ma34'] = close.rolling(34).mean() # 34日均线data['X16'] = data[['ma13', 'ma34']].max(axis=1) # X_16: 13/34均线最大值data['X17'] = data[['ma13', 'ma34']].min(axis=1) # X_17: 13/34均线最小值# 2. 计算震荡辅助指标(对应公式X_7~X_13,用于过滤信号)hhv_x1 = high.rolling(self.X1).max() # X_1周期内的最高价llv_x1 = low.rolling(self.X1).min() # X_1周期内的最低价data['X7'] = (hhv_x1 - close) / (hhv_x1 - llv_x1) * 100 - self.X2data['X8'] = data['X7'].rolling(self.X1).mean() + 100 # SMA平滑(用rolling mean近似)data['X9'] = (close - llv_x1) / (hhv_x1 - llv_x1) * 100data['X10'] = data['X9'].rolling(3).mean()data['X11'] = data['X10'].rolling(3).mean() + 100data['X12'] = data['X11'] - data['X8']data['X13'] = np.where(data['X12'] > self.X3, data['X12'] - self.X3, 0) * 2.5# 3. 生成核心交易信号(红买、绿停、黄观望)data['红买信号'] = close < data['X17'] # 红买:收盘价<X17data['绿停信号'] = close > data['X16'] # 绿停:收盘价>X16data['黄观望信号'] = (data['X16'] >= close) & (close >= data['X17']) # 黄观望:介于两者之间# 4. 生成标准化交易信号(1=买入,-1=卖出,0=持有/观望),便于回测data['交易信号'] = 0data.loc[data['红买信号'], '交易信号'] = 1 # 买入信号data.loc[data['绿停信号'], '交易信号'] = -1 # 卖出信号# 去除空值,确保回测有效性data.dropna(inplace=True)return data
def plot_signals(df, stock_code):"""可视化股票K线、均线和交易信号参数:df: 带信号的DataFrame;stock_code: 股票代码"""plt.rcParams['font.sans-serif'] = ['SimHei'] # 解决中文显示问题plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题fig, ax = plt.subplots(figsize=(12, 6))# 绘制K线(简化版,用收盘价线代替)ax.plot(df.index, df['close'], color='gray', linewidth=1.5, label='收盘价')# 绘制13/34日均线(策略核心均线)ax.plot(df.index, df['ma13'], color='orange', linewidth=1.2, label='13日均线')ax.plot(df.index, df['ma34'], color='blue', linewidth=1.2, label='34日均线')# 标注红买、绿停信号buy_signals = df[df['红买信号']]sell_signals = df[df['绿停信号']]ax.scatter(buy_signals.index, buy_signals['close'], marker='^', color='red', s=100, label='红买信号')ax.scatter(sell_signals.index, sell_signals['close'], marker='v', color='green', s=100, label='绿停信号')# 图表设置ax.set_title(f'{stock_code} 红买绿停策略信号可视化', fontsize=14)ax.set_ylabel('价格(元)', fontsize=12)ax.legend(loc='best')ax.grid(True, alpha=0.3)plt.xticks(rotation=45)plt.tight_layout()plt.show()# 测试:单只股票信号生成与可视化if __name__ == "__main__":# 1. 读取单只股票的.day文件(替换为你的通达信文件路径)stock_file = r"D:\软件安装\通达信\vipdoc\sz\lday\sz000001.day" # 平安银行k_data = parse_tdx_day(stock_file)if k_data is None:print("数据解析失败,请检查文件路径或文件完整性")exit()# 2. 生成策略信号strategy = RedGreenStrategy()signal_df = strategy.calculate_signals(k_data)# 3. 可视化信号plot_signals(signal_df, "sz000001(平安银行)")


运行代码后,会生成包含收盘价、13/34日均线、红买绿停信号的图表,可直观看到:红买信号多出现于价格跌破双均线区间低位,绿停信号多出现于价格突破双均线区间高位,与策略逻辑完全一致。





单只股票的信号可视化只能初步验证逻辑,批量回测才能真正判断策略的实战价值——通过回测全市场(或指定板块)股票,计算核心评估因子,判断策略是否能稳定盈利。


整合“文件扫描+数据解析+策略信号+回测评估”,批量处理所有通达信.day文件,输出回测报告。


class StrategyBacktester:def __init__(self, initial_capital=1000000, fee_rate=0.0003):"""回测引擎初始化参数:initial_capital: 初始资金(默认100万);fee_rate: 手续费(默认万3,贴合A股实盘)"""self.initial_capital = initial_capitalself.fee_rate = fee_ratedef backtest_single_stock(self, df, stock_code):"""单只股票回测,计算核心评估因子参数:df: 带信号的DataFrame;stock_code: 股票代码返回:回测结果字典(包含收益率、最大回撤等核心指标)"""try:data = df.copy()# 生成持仓信号:信号次日执行(避免未来函数)data['持仓'] = data['交易信号'].replace(0, np.nan).ffill().fillna(0)data['持仓'] = data['持仓'].shift(1).fillna(0)# 计算每日收益data['每日收益率'] = data['close'].pct_change().fillna(0)data['策略收益率'] = data['持仓'] * data['每日收益率']# 扣除手续费(每次交易收取,买卖都扣)trade_changes = data['持仓'].diff().fillna(0).abs() # 持仓变化(买卖动作)data['策略收益率'] -= trade_changes * self.fee_rate# 计算累计资产和核心评估因子data['累计资产'] = self.initial_capital * (1 + data['策略收益率']).cumprod()final_capital = data['累计资产'].iloc[-1]# 核心评估因子(量化实战必看)total_return = (final_capital / self.initial_capital) - 1 # 总收益率annual_return = total_return * 252 / len(data) # 年化收益率(252个交易日)# 最大回撤(风险核心指标)data['累计最大值'] = data['累计资产'].cummax()data['回撤'] = (data['累计资产'] - data['累计最大值']) / data['累计最大值']max_drawdown = data['回撤'].min()# 交易次数、胜率、盈亏比trades = data[data['交易信号'] != 0]trade_returns = []buy_price = Nonefor _, row in data.iterrows():if row['交易信号'] == 1:buy_price = row['close']elif row['交易信号'] == -1 and buy_price is not None:trade_return = (row['close'] - buy_price) / buy_pricetrade_returns.append(trade_return)buy_price = Nonetrade_count = len(trade_returns)win_rate = len([x for x in trade_returns if x > 0]) / trade_count if trade_count > 0 else 0# 盈亏比:平均盈利/平均亏损profit_returns = [x for x in trade_returns if x > 0]loss_returns = [abs(x) for x in trade_returns if x < 0]avg_profit = np.mean(profit_returns) if profit_returns else 0avg_loss = np.mean(loss_returns) if loss_returns else 0profit_loss_ratio = avg_profit / avg_loss if avg_loss != 0 else 0# 夏普比率(风险调整后收益,>1合格,>2优秀)sharpe_ratio = np.mean(data['策略收益率']) / np.std(data['策略收益率']) * np.sqrt(252) if np.std(data['策略收益率']) != 0 else 0return {'股票代码': stock_code,'初始资金': self.initial_capital,'最终资金': round(final_capital, 2),'总收益率(%)': round(total_return * 100, 2),'年化收益率(%)': round(annual_return * 100, 2),'最大回撤(%)': round(max_drawdown * 100, 2),'交易次数': trade_count,'胜率(%)': round(win_rate * 100, 2),'盈亏比': round(profit_loss_ratio, 2),'夏普比率': round(sharpe_ratio, 2),'数据天数': len(data)}except Exception as e:print(f"回测{stock_code}失败:{e}")return None# 批量回测主函数def batch_backtest(data_paths, output_dir='./红买绿停回测结果'):"""批量回测指定路径下的所有.day文件参数:data_paths: 通达信.day文件所在目录(可传入多个);output_dir: 回测结果保存目录"""# 创建结果保存目录os.makedirs(output_dir, exist_ok=True)# 初始化工具backtester = StrategyBacktester()strategy = RedGreenStrategy()result_list = []# 扫描所有.day文件for data_path in data_paths:if not os.path.exists(data_path):print(f"路径不存在:{data_path}")continueprint(f"正在扫描目录:{data_path}")day_files = [f for f in os.listdir(data_path) if f.endswith('.day')]# 批量处理每个文件for filename in tqdm(day_files, desc=f"处理{os.path.basename(data_path)}"):file_path = os.path.join(data_path, filename)stock_code = filename.replace('.day', '') # 提取股票代码(如sh600000)# 解析数据、生成信号、执行回测k_data = parse_tdx_day(file_path)if k_data is None:continuesignal_df = strategy.calculate_signals(k_data)if len(signal_df) < 30:continuebacktest_result = backtester.backtest_single_stock(signal_df, stock_code)if backtest_result:result_list.append(backtest_result)# 保存回测汇总报告result_df = pd.DataFrame(result_list)result_csv = os.path.join(output_dir, '红买绿停策略回测汇总.csv')result_df.to_csv(result_csv, index=False, encoding='utf-8-sig')print(f"\n批量回测完成!汇总报告已保存至:{result_csv}")# 打印策略整体评估if not result_df.empty:print("\n==================== 策略整体评估 ====================")print(f"回测股票总数:{len(result_df)} 只")print(f"平均总收益率:{round(result_df['总收益率(%)'].mean(), 2)}%")print(f"平均年化收益率:{round(result_df['年化收益率(%)'].mean(), 2)}%")print(f"平均最大回撤:{round(result_df['最大回撤(%)'].mean(), 2)}%")print(f"平均胜率:{round(result_df['胜率(%)'].mean(), 2)}%")print(f"平均盈亏比:{round(result_df['盈亏比'].mean(), 2)}")print(f"平均夏普比率:{round(result_df['夏普比率'].mean(), 2)}")else:print("未完成任何有效回测,请检查数据路径或文件完整性")# 执行批量回测(替换为你的通达信数据路径)if __name__ == "__main__":sz_data_path = r"D:\软件安装\通达信\vipdoc\sz\lday" # 深圳股票数据路径sh_data_path = r"D:\软件安装\通达信\vipdoc\sh\lday" # 上海股票数据路径batch_backtest([sz_data_path, sh_data_path])


批量回测后,会生成一个CSV汇总报告,包含每只股票的核心评估因子,新手只需重点关注以下6个指标,就能快速判断策略优劣:


评估因子 | 解读 | 合格标准 |
|---|---|---|
年化收益率 | 策略一年能获得的平均收益,核心盈利指标 | ≥10%(超过银行理财,贴合A股实战) |
最大回撤 | 策略最大亏损幅度,核心风险指标 | ≤-20%(回撤越小,风险越低) |
胜率 | 盈利交易占总交易的比例 | ≥50%(盈利交易多于亏损交易) |
盈亏比 | 平均盈利/平均亏损,决定策略长期盈利能力 | ≥1.5(赚的比亏的多,越多越好) |
夏普比率 | 风险调整后收益,衡量“风险vs收益”的性价比 | ≥1(合格),≥2(优秀) |
交易次数 | 策略活跃度,过多易增加手续费,过少则盈利机会少 | 每年50-100次(波段策略合理区间) |


补充说明:红买绿停策略的回测结果通常为“中等收益、中等风险”——平均年化10%-20%,最大回撤-15%~-25%,胜率50%-60%,盈亏比1.5-2.0,适合稳健型波段交易者,不追求高收益,但求稳定盈利。






基础策略落地后,还需要结合实战场景优化,避免无效信号和不必要的亏损,以下4个技巧是新手进阶的关键,也是实战中验证有效的优化方向。




策略默认参数(X1=35、X2=35、X3=3)适合震荡市,可根据行情调整:
震荡市(默认):X1=35、X2=35、X3=3,信号稳定,避免频繁交易;
弱趋势市:X1=25、X2=30、X3=2,降低信号阈值,捕捉更多波段机会;
强趋势市:X1=45、X2=40、X3=4,提高信号阈值,过滤震荡信号,避免过早卖出。
优化方法:用某一板块股票(如沪深300成分股)回测不同参数,选择“年化收益率最高、最大回撤最小”的组合。



基础策略仅看价格和均线,容易出现“假信号”(如无量跌破X17、无量突破X16),添加成交量过滤可大幅提升信号准确率:

# 在calculate_signals函数中添加成交量过滤# 新增:成交量大于近5日平均成交量的1.2倍,才确认信号有效data['5日平均成交量'] = data['volume'].rolling(5).mean()data['红买信号'] = (close < data['X17']) & (data['volume'] > data['5日平均成交量'] * 1.2)data['绿停信号'] = (close > data['X16']) & (data['volume'] > data['5日平均成交量'] * 1.2)


逻辑:放量突破/跌破才是真实趋势信号,缩量信号多为震荡调整,可过滤掉大部分假信号,提升胜率。



基础策略只有“绿停”卖出信号,缺乏止盈止损,实战中可添加固定止盈止损,避免盈利回吐或亏损扩大:
止盈:买入后,当价格上涨7%-10%,无论是否触发绿停信号,主动卖出(落袋为安);
止损:买入后,当价格下跌3%-5%,无论是否触发绿停信号,主动卖出(控制亏损)。
代码实现:在回测函数中添加止盈止损逻辑,替换原有“仅靠绿停信号卖出”的规则,具体可参考文末示例代码。



红买绿停策略在震荡市和弱趋势市表现最佳,在极端单边牛市/熊市中表现不佳,实战中需避开极端行情:
单边牛市:可暂时关闭策略,或调整参数(X1=45),避免过早卖出,错过主升浪;
单边熊市:可暂停交易,或仅小仓位试错,避免频繁买入导致持续亏损;
选择标的:优先选择业绩稳定、波动适中的蓝筹股或ETF,避开妖股、ST股(信号混乱,风险高)。






不追求“完美信号”:策略没有100%胜率,接受一定的亏损,长期坚持才能实现稳定盈利;
回测≠实盘:回测是基于历史数据,实盘会受到手续费、滑点、行情突变等影响,需预留一定的误差空间;
持续优化:市场行情在变化,策略参数和过滤条件也需要定期调整,不能一成不变。


