在上一篇文章中,我们探讨了如何用AI作为强大的“信息分析师”。今天,我们要更进一步,将AI的洞察力与代码结合,构建一个简单的自动化交易策略。

我们将从零开始,用Python实现一个“双因子”验证的量化交易模型。这个模型结合了经典的技术分析和现代的AI情绪分析,旨在寻找更高确定性的交易信号。

!!! 超级重要的免责声明 !!!

在开始之前,我必须用最严肃的语气强调:

  1. 这是一个玩具模型:为了教学目的,这个策略被极度简化。它完全忽略了交易成本、滑点、市场冲击、分红配股等一系列将扼杀简单策略的现实因素。
  2. 绝不保证盈利:这个模型的历史回测表现不代表未来,它很可能会亏钱。其设计的核心目的是展示一种思路,而不是创造一个盈利机器。
  3. 切勿用于实盘永远不要将本文的代码直接用于真实资金的交易。这非常危险!

请将本文视为一次学习和探索,一次思维的体操,而非一本致富秘籍。


策略思想:当移动平均线遇上AI情绪

单一的信号往往是不可靠的。价格突破了移动平均线,可能是假突破;新闻情绪高涨,可能是短期的非理性狂热。

我们的策略试图通过“双重验证”来提高信号的质量:

  1. 技术因子:使用简单移动平均线(SMA)。我们计算两条移动平均线:一条短期的(如20日),一条长期的(如50日)。当短期线上穿长期线(形成“黄金交叉”)时,我们认为技术面看涨。反之(“死亡交叉”)则看跌。
  2. AI情绪因子:我们会创建一个模拟函数 get_ai_sentiment_score()。在真实的系统中,它会去调用大语言模型,分析与该股票相关的最新新闻、社交媒体讨论,然后返回一个**从-1(极度悲观)到+1(极度乐观)**的情绪得分。
  3. 交易信号
    • 买入信号: 当且仅当,技术上形成“黄金交叉” 并且 AI情绪得分大于一个乐观阈值(如 0.5)。
    • 卖出信号: 当且仅当,技术上形成“死亡交叉” 并且 AI情绪得分小于一个悲观阈值(如 -0.5)。
    • 持仓/空仓: 其他所有情况,我们都按兵不动,避免在信号不明确时进行交易。

Let’s Code: 用Python实现策略

现在,让我们把上面的思想翻译成代码。

第一步:环境准备与数据获取

首先,你需要安装几个关键的Python库。

pip install yfinance pandas numpy matplotlib

然后,我们编写代码来获取一只股票的历史数据。这里我们以阿里巴巴(BABA)为例。

import yfinance as yf
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# 下载股票数据
def get_stock_data(ticker, start_date, end_date):
    """使用yfinance获取股票数据"""
    data = yf.download(ticker, start=start_date, end=end_date)
    return data

# --- 主程序区 ---
ticker = 'BABA'
start_date = '2022-01-01'
end_date = '2024-01-01'
stock_data = get_stock_data(ticker, start_date, end_date)

print("数据预览:")
print(stock_data.head())

第二步:计算技术指标

我们来计算短期和长期的移动平均线。

# 计算移动平均线
short_window = 20
long_window = 50

stock_data['Short_SMA'] = stock_data['Close'].rolling(window=short_window, min_periods=1).mean()
stock_data['Long_SMA'] = stock_data['Close'].rolling(window=long_window, min_periods=1).mean()

第三步:模拟AI情绪分析

这是最关键的环节。在真实系统中,这里会是一个复杂的API调用。为了让代码可以独立运行,我们用一个随机数生成器来模拟这个过程。

def get_ai_sentiment_score(date):
    """
    这是一个模拟函数。
    在真实的系统中,这里会调用一个复杂的AI模型API,
    输入日期或相关新闻,输出一个市场情绪得分。
    为了演示,我们这里使用随机数模拟。
    """
    # 设定随机种子以保证结果可复现
    np.random.seed(abs(hash(date)) % (10**8))
    # 生成一个-1到1之间的随机数
    return np.random.uniform(-1, 1)

# 将模拟的AI情绪得分应用到我们的数据上
stock_data['AI_Sentiment'] = stock_data.index.map(get_ai_sentiment_score)

再次强调:上面这个函数是整个策略中最“虚假”的部分,但它清晰地标明了AI应该在何处发挥作用。

第四步:回测策略

现在我们来写真正的交易逻辑,并在历史数据上进行回测。

# 初始化账户信息
initial_capital = 100000.0
capital = initial_capital
positions = 0
portfolio = pd.DataFrame(index=stock_data.index).fillna(0.0)
portfolio['holdings'] = 0.0
portfolio['cash'] = initial_capital
portfolio['total'] = initial_capital

# 生成信号
# 'signal'列: 1表示金叉, -1表示死叉, 0表示无交叉
stock_data['signal'] = 0
stock_data.loc[short_window:, 'signal'] = np.where(
    stock_data.loc[short_window:, 'Short_SMA'] > stock_data.loc[short_window:, 'Long_SMA'], 1, 0)
stock_data['signal'] = stock_data['signal'].diff()

# AI情绪阈值
sentiment_threshold = 0.5

# 遍历数据进行回测
for i in range(len(stock_data)):
    # 买入逻辑
    if (stock_data['signal'][i] == 1 and
        stock_data['AI_Sentiment'][i] > sentiment_threshold and
        capital > stock_data['Close'][i]):
        
        positions = capital // stock_data['Close'][i]
        cost = positions * stock_data['Close'][i]
        capital -= cost
        
        portfolio.loc[stock_data.index[i], 'holdings'] = positions * stock_data['Close'][i]
        portfolio.loc[stock_data.index[i]:, 'cash'] = capital
        print(f"{stock_data.index[i].date()}: 买入 {positions} 股")

    # 卖出逻辑
    elif (stock_data['signal'][i] == -1 and
          stock_data['AI_Sentiment'][i] < -sentiment_threshold and
          positions > 0):
          
        capital += positions * stock_data['Close'][i]
        print(f"{stock_data.index[i].date()}: 卖出 {positions} 股")
        positions = 0
        
        portfolio.loc[stock_data.index[i]:, 'cash'] = capital
        
    # 更新每日资产总值
    portfolio.loc[stock_data.index[i], 'holdings'] = positions * stock_data['Close'][i]
    portfolio.loc[stock_data.index[i], 'total'] = portfolio.loc[stock_data.index[i], 'cash'] + portfolio.loc[stock_data.index[i], 'holdings']

final_value = portfolio['total'][-1]
print(f"\n初始资金: {initial_capital:.2f}")
print(f"最终资产: {final_value:.2f}")
print(f"策略收益率: {(final_value - initial_capital) / initial_capital * 100:.2f}%")

第五步:结果可视化

一张图胜过千言万语。我们把交易信号、股价和移动平均线画在一起。

plt.figure(figsize=(14, 7))

# 绘制股价和移动平均线
plt.plot(stock_data['Close'], label='Close Price', alpha=0.5)
plt.plot(stock_data['Short_SMA'], label=f'{short_window}-Day SMA', alpha=0.8)
plt.plot(stock_data['Long_SMA'], label=f'{long_window}-Day SMA', alpha=0.8)

# 绘制买入信号
buy_signals = stock_data[(stock_data['signal'] == 1) & (stock_data['AI_Sentiment'] > sentiment_threshold)]
plt.plot(buy_signals.index, stock_data.loc[buy_signals.index]['Short_SMA'], '^', markersize=12, color='g', label='Buy Signal (Golden Cross + Positive AI)')

# 绘制卖出信号
sell_signals = stock_data[(stock_data['signal'] == -1) & (stock_data['AI_Sentiment'] < -sentiment_threshold)]
plt.plot(sell_signals.index, stock_data.loc[sell_signals.index]['Short_SMA'], 'v', markersize=12, color='r', label='Sell Signal (Death Cross + Negative AI)')

plt.title(f'{ticker} Trading Strategy Backtest')
plt.xlabel('Date')
plt.ylabel('Price')
plt.legend()
plt.grid()
plt.show()

# 绘制资产曲线
plt.figure(figsize=(14, 7))
plt.plot(portfolio['total'], label='Portfolio Value')
plt.title('Portfolio Value Over Time')
plt.xlabel('Date')
plt.ylabel('Total Value')
plt.legend()
plt.grid()
plt.show()

总结与反思

运行完上面的代码,你可能会得到一个看起来还不错(或者很糟糕)的回测结果。但这不重要!

重要的是,我们完成了一次从 想法 -> 策略 -> 代码 -> 回测 的完整流程。我们清晰地看到了AI可以在哪个环节赋能传统的技术分析。

这个模型最大的弱点是什么?

  1. AI情绪是假的:这是核心。真实的AI情绪分析需要强大的NLP模型和海量数据源,本身就是一个复杂的工程。
  2. 参数是拍脑袋定的:为什么是20/50日均线?为什么情绪阈值是0.5?这些都需要通过更严谨的方法(如参数寻优)来确定,但那样又极易陷入“过度拟合”。
  3. 现实因素的缺失:没有交易成本,买卖都按收盘价成交,这些都是过于理想的假设。

这个玩具模型真正的价值,是启发我们思考:如何将AI提供的非结构化信息(如新闻、研报)量化成一个可执行的因子,并将其融入到系统化的交易框架中。这才是AI量化交易的星辰大海。