机器学习快速入门

# 机器学习快速入门

# 学习目标

通过本章,你将掌握:

  • 机器学习的基本概念和分类
  • 监督学习、非监督学习、强化学习
  • scikit-learn的使用
  • 在量化交易中应用机器学习

# 什么是机器学习

**机器学习(Machine Learning)**是一种让计算机从数据中学习规律,并用于预测和决策的技术。

# 核心思想

传统编程:规则 + 数据 → 结果
机器学习:数据 + 结果 → 规则
1
2

# 在量化交易中的应用

  1. 价格预测:预测股票未来涨跌
  2. 因子挖掘:发现有效的选股因子
  3. 风险管理:识别市场异常和风险
  4. 策略优化:优化交易参数和时机

# 机器学习分类

# 1. 监督学习 (Supervised Learning)

定义:从标注数据中学习输入到输出的映射关系

特点:

  • 有明确的目标变量(标签)
  • 需要人工标注数据
  • 可以评估预测准确性

类型:

  • 分类:预测离散标签(涨/跌)
  • 回归:预测连续值(价格)

常用算法:

  • 线性回归
  • 逻辑回归
  • 决策树
  • 随机森林
  • 支持向量机(SVM)
  • 神经网络

# 2. 非监督学习 (Unsupervised Learning)

定义:从无标注数据中发现隐藏的模式和结构

特点:

  • 没有目标变量
  • 自动发现数据规律
  • 用于探索性分析

类型:

  • 聚类:将数据分组(股票分类)
  • 降维:减少特征数量(PCA)
  • 异常检测:发现异常数据点

常用算法:

  • K-Means聚类
  • 层次聚类
  • PCA主成分分析
  • t-SNE

# 3. 强化学习 (Reinforcement Learning)

定义:通过与环境交互,学习最优决策策略

特点:

  • 通过奖励反馈学习
  • 适合序列决策问题
  • 需要定义状态、动作、奖励

在量化中的应用:

  • 自动交易决策
  • 仓位管理优化
  • 动态对冲策略

# 机器学习流程

1. 数据收集
   ↓
2. 数据预处理
   ↓
3. 特征工程
   ↓
4. 模型选择
   ↓
5. 模型训练
   ↓
6. 模型评估
   ↓
7. 模型优化
   ↓
8. 模型部署
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 完整代码示例:股票涨跌预测

"""
使用机器学习预测股票涨跌
"""

import pandas as pd
import numpy as np
import yfinance as yf
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix
import matplotlib.pyplot as plt
import seaborn as sns

class StockMLPredictor:
    """股票机器学习预测器"""

    def __init__(self, symbol, lookback=20, forecast=1):
        """
        初始化
        :param symbol: 股票代码
        :param lookback: 回望期(用多少天的数据预测)
        :param forecast: 预测期(预测未来几天)
        """
        self.symbol = symbol
        self.lookback = lookback
        self.forecast = forecast
        self.data = None
        self.features = None
        self.labels = None
        self.model = None
        self.scaler = StandardScaler()

    def download_data(self, start_date, end_date):
        """下载数据"""
        print(f"下载 {self.symbol} 数据...")
        self.data = yf.download(self.symbol, start=start_date, end=end_date)
        print(f"下载完成!共 {len(self.data)} 条记录\n")
        return self

    def create_features(self):
        """创建特征"""
        print("创建特征...")

        df = self.data.copy()

        # 技术指标特征
        # 1. 收益率
        df['return'] = df['Close'].pct_change()

        # 2. 移动平均
        for window in [5, 10, 20, 60]:
            df[f'ma{window}'] = df['Close'].rolling(window).mean()
            df[f'ma{window}_ratio'] = df['Close'] / df[f'ma{window}'] - 1

        # 3. 波动率
        df['volatility_20'] = df['return'].rolling(20).std()

        # 4. 成交量相关
        df['volume_ratio'] = df['Volume'] / df['Volume'].rolling(20).mean()

        # 5. RSI
        df['rsi'] = self._calculate_rsi(df['Close'], 14)

        # 6. MACD
        exp1 = df['Close'].ewm(span=12, adjust=False).mean()
        exp2 = df['Close'].ewm(span=26, adjust=False).mean()
        df['macd'] = exp1 - exp2
        df['macd_signal'] = df['macd'].ewm(span=9, adjust=False).mean()
        df['macd_hist'] = df['macd'] - df['macd_signal']

        # 7. 布林带
        df['bb_middle'] = df['Close'].rolling(20).mean()
        df['bb_std'] = df['Close'].rolling(20).std()
        df['bb_upper'] = df['bb_middle'] + 2 * df['bb_std']
        df['bb_lower'] = df['bb_middle'] - 2 * df['bb_std']
        df['bb_position'] = (df['Close'] - df['bb_lower']) / (df['bb_upper'] - df['bb_lower'])

        # 创建标签:未来N天涨跌
        df['future_return'] = df['Close'].pct_change(self.forecast).shift(-self.forecast)
        df['label'] = (df['future_return'] > 0).astype(int)  # 1表示涨,0表示跌

        # 删除NaN
        df = df.dropna()

        # 选择特征列
        feature_cols = [col for col in df.columns if col not in
                       ['Open', 'High', 'Low', 'Close', 'Volume', 'Adj Close',
                        'future_return', 'label']]

        self.features = df[feature_cols]
        self.labels = df['label']

        print(f"特征创建完成!共 {len(feature_cols)} 个特征")
        print(f"特征列表: {feature_cols[:5]}...\n")

        return self

    def _calculate_rsi(self, prices, period=14):
        """计算RSI"""
        delta = prices.diff()
        gain = (delta.where(delta > 0, 0)).rolling(window=period).mean()
        loss = (-delta.where(delta < 0, 0)).rolling(window=period).mean()
        rs = gain / loss
        rsi = 100 - (100 / (1 + rs))
        return rsi

    def train_model(self, test_size=0.2):
        """训练模型"""
        print("训练模型...")

        # 划分数据集
        X_train, X_test, y_train, y_test = train_test_split(
            self.features, self.labels,
            test_size=test_size,
            shuffle=False  # 时间序列不打乱
        )

        # 特征标准化
        X_train_scaled = self.scaler.fit_transform(X_train)
        X_test_scaled = self.scaler.transform(X_test)

        # 训练随机森林
        self.model = RandomForestClassifier(
            n_estimators=100,
            max_depth=10,
            random_state=42
        )
        self.model.fit(X_train_scaled, y_train)

        # 预测
        y_train_pred = self.model.predict(X_train_scaled)
        y_test_pred = self.model.predict(X_test_scaled)

        # 评估
        train_acc = accuracy_score(y_train, y_train_pred)
        test_acc = accuracy_score(y_test, y_test_pred)

        print(f"训练集准确率: {train_acc:.4f}")
        print(f"测试集准确率: {test_acc:.4f}\n")

        # 详细报告
        print("分类报告:")
        print(classification_report(y_test, y_test_pred,
                                   target_names=['下跌', '上涨']))

        # 混淆矩阵
        cm = confusion_matrix(y_test, y_test_pred)
        self._plot_confusion_matrix(cm)

        # 特征重要性
        self._plot_feature_importance()

        return self

    def _plot_confusion_matrix(self, cm):
        """绘制混淆矩阵"""
        plt.figure(figsize=(8, 6))
        sns.heatmap(cm, annot=True, fmt='d', cmap='Blues',
                   xticklabels=['下跌', '上涨'],
                   yticklabels=['下跌', '上涨'])
        plt.title('混淆矩阵')
        plt.ylabel('真实标签')
        plt.xlabel('预测标签')
        plt.tight_layout()
        plt.savefig('confusion_matrix.png', dpi=300)
        print("混淆矩阵已保存: confusion_matrix.png")
        plt.show()

    def _plot_feature_importance(self):
        """绘制特征重要性"""
        importances = self.model.feature_importances_
        indices = np.argsort(importances)[::-1][:10]  # Top 10

        plt.figure(figsize=(10, 6))
        plt.bar(range(10), importances[indices])
        plt.xticks(range(10), self.features.columns[indices], rotation=45, ha='right')
        plt.title('Top 10 特征重要性')
        plt.xlabel('特征')
        plt.ylabel('重要性')
        plt.tight_layout()
        plt.savefig('feature_importance.png', dpi=300)
        print("特征重要性已保存: feature_importance.png\n")
        plt.show()

    def predict(self, new_data):
        """预测新数据"""
        new_data_scaled = self.scaler.transform(new_data)
        prediction = self.model.predict(new_data_scaled)
        probability = self.model.predict_proba(new_data_scaled)
        return prediction, probability

def main():
    """主函数"""
    # 创建预测器
    predictor = StockMLPredictor(
        symbol='AAPL',
        lookback=20,
        forecast=1
    )

    # 运行完整流程
    predictor.download_data('2020-01-01', '2023-12-31') \
             .create_features() \
             .train_model()

    print("=" * 50)
    print("机器学习预测完成!")
    print("=" * 50)

if __name__ == '__main__':
    main()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

# 关键概念

# 过拟合 vs 欠拟合

过拟合(Overfitting)

  • 模型在训练集上表现很好,测试集表现差
  • 原因:模型过于复杂,记住了噪声
  • 解决:正则化、减少特征、增加数据

欠拟合(Underfitting)

  • 模型在训练集和测试集上都表现差
  • 原因:模型过于简单,没有捕捉规律
  • 解决:增加特征、使用更复杂模型

# 偏差-方差权衡

总误差 = 偏差² + 方差 + 不可约误差

偏差(Bias):模型的假设与真实情况的差距
方差(Variance):模型对训练数据的敏感程度
1
2
3
4

# 常见问题

# Q1: 准确率高就是好模型吗?

A: 不一定!

在量化交易中:

  • 准确率60% + 盈亏比3:1 → 赚钱
  • 准确率80% + 盈亏比1:2 → 亏钱

关键指标:

  • 精确率(Precision)
  • 召回率(Recall)
  • F1-Score
  • 最终收益率

# Q2: 如何防止过拟合?

方法:

  1. 交叉验证
  2. 正则化(L1、L2)
  3. 早停(Early Stopping)
  4. Dropout
  5. 简化模型
  6. 增加训练数据

# Q3: 时间序列数据如何划分?

A: 必须按时间顺序!

# 错误:随机打乱
X_train, X_test = train_test_split(X, y, shuffle=True)

# 正确:按时间划分
split_point = int(len(X) * 0.8)
X_train = X[:split_point]
X_test = X[split_point:]
1
2
3
4
5
6
7

# 进阶资源

# 推荐课程

  1. 吴恩达机器学习 - Coursera
  2. fast.ai实战课程
  3. Kaggle Learn

# 推荐书籍

  1. 《Python机器学习》 - Sebastian Raschka
  2. 《统计学习方法》 - 李航
  3. 《机器学习实战》 - Peter Harrington

# 实践平台

  • Kaggle:数据竞赛
  • 天池:阿里云竞赛平台
  • 和鲸社区:国内数据科学平台

# 下一步

  1. 深入学习

  2. 实战练习

    • 完成股票涨跌预测项目
    • 尝试不同的特征组合
    • 对比不同算法效果
  3. 继续进阶

    • 学习深度学习
    • 探索强化学习
    • 研究集成学习

机器学习是量化交易的强大工具,但要记住:好特征比复杂模型更重要!

上一篇:趋势跟踪策略 | 下一篇:特征工程在量化中的应用

Last Updated: 9/25/2026, 2:08:32 PM