基于SVM算法的股票买卖点判断
豆包的案例:
点击查看代码
import pandas as pd
import numpy as np
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
import yfinance as yf
# 1. 数据收集
def get_stock_data(ticker, start_date, end_date):
data = yf.download(ticker, start=start_date, end=end_date)
return data
# 2. 特征工程
def feature_engineering(data):
data['SMA_5'] = data['Close'].rolling(window=5).mean()
data['SMA_20'] = data['Close'].rolling(window=20).mean()
data['RSI'] = calculate_rsi(data['Close'], 14)
data.dropna(inplace=True)
return data
# 计算相对强弱指标(RSI)
def calculate_rsi(close_prices, period=14):
deltas = np.diff(close_prices)
seed = deltas[:period + 1]
up = seed[seed >= 0].sum() / period
down = -seed[seed < 0].sum() / period
rs = up / down
rsi = np.zeros_like(close_prices)
rsi[:period] = 100. - 100. / (1. + rs)
for i in range(period, len(close_prices)):
delta = deltas[i - 1]
if delta > 0:
upval = delta
downval = 0.
else:
upval = 0.
downval = -delta
up = (up * (period - 1) + upval) / period
down = (down * (period - 1) + downval) / period
rs = up / down
rsi[i] = 100. - 100. / (1. + rs)
return rsi
# 3. 标签定义
def define_labels(data):
data['Label'] = np.where(data['Close'].shift(-1) > data['Close'], 1, 0)
data.dropna(inplace=True)
return data
# 4. 数据划分
def split_data(data):
X = data[['SMA_5', 'SMA_20', 'RSI']]
y = data['Label']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
return X_train, X_test, y_train, y_test
# 5. 模型训练
def train_model(X_train, y_train):
model = SVC(kernel='rbf', random_state=42)
model.fit(X_train, y_train)
return model
# 6. 模型评估
def evaluate_model(model, X_test, y_test):
y_pred = model.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
print(f"模型准确率: {accuracy}")
# 7. 预测买卖点
def predict_trading_points(model, data):
X = data[['SMA_5', 'SMA_20', 'RSI']]
predictions = model.predict(X)
data['Prediction'] = predictions
return data
if __name__ == "__main__":
ticker = 'AAPL'
start_date = '2020-01-01'
end_date = '2024-01-01'
# 数据收集
data = get_stock_data(ticker, start_date, end_date)
# 特征工程
data = feature_engineering(data)
# 标签定义
data = define_labels(data)
# 数据划分
X_train, X_test, y_train, y_test = split_data(data)
# 模型训练
model = train_model(X_train, y_train)
# 模型评估
evaluate_model(model, X_test, y_test)
# 预测买卖点
data = predict_trading_points(model, data)
print(data[['Close', 'Prediction']])
下面为你详细阐述运用支持向量机(SVM)来计算股票买卖点的具体方法,同时会给出 Python 代码示例。
解决步骤
- 数据收集
你需要获取股票的历史数据,涵盖开盘价、收盘价、最高价、最低价、成交量等信息。可以借助第三方库(如pandas-datareader)来获取这些数据。 - 特征工程
对收集到的数据进行处理,提取出对股票买卖点有影响的特征。常见的特征有移动平均线、相对强弱指标(RSI)、布林带等。 - 标签定义
依据股票的历史数据,定义买卖点的标签。例如,当未来一段时间内股票价格上涨时,标签设为 1(买入);当价格下跌时,标签设为 0(卖出)。 - 数据划分
把处理好的数据划分为训练集和测试集,一般按照 80% 和 20% 的比例划分。 - 模型训练
运用训练集的数据对 SVM 模型进行训练。 - 模型评估
使用测试集的数据对训练好的模型进行评估,计算模型的准确率、召回率等指标。 - 预测买卖点
使用训练好的模型对新的数据进行预测,得到股票的买卖点。
Python 代码示例
svm-stock-prediction
使用SVM计算股票买卖点的Python代码 V1
生成 svm_stock_prediction.py
代码解释
数据收集:借助yfinance库下载指定股票在特定时间段内的历史数据。
特征工程:计算 5 日和 20 日的简单移动平均线(SMA)以及相对强弱指标(RSI)。
标签定义:若下一日的收盘价高于当日收盘价,则标签设为 1(买入);反之设为 0(卖出)。
数据划分:把数据划分为训练集和测试集,比例为 80% 和 20%。
模型训练:使用径向基函数(RBF)核的 SVM 模型进行训练。
模型评估:计算模型在测试集上的准确率。
预测买卖点:使用训练好的模型对所有数据进行预测,得到股票的买卖点。
注意事项
股票市场复杂多变,SVM 模型只能作为参考,不能完全依赖其预测结果进行买卖决策。
可以尝试不同的特征和模型参数,以提高模型的性能。
DS给出的范例
使用支持向量机(SVM)预测股票买卖点的方法
支持向量机(SVM)是一种强大的机器学习算法,可以用于股票买卖点的预测。下面我将详细介绍如何使用SVM来实现这一目标,并提供完整的Python实现方案。
方法概述
数据准备:收集历史股票数据并提取相关特征
标记买卖点:定义买卖信号的标准
特征工程:构建有助于预测的技术指标
模型训练:使用SVM学习买卖信号模式
策略回测:评估买卖信号的盈利能力
具体实现步骤
- 数据准备
首先需要获取历史股票数据,可以使用以下方法之一:
Yahoo Finance API (yfinance)
Alpha Vantage API
本地存储的历史数据
python
复制
import yfinance as yf
import pandas as pd
import numpy as np
from sklearn import svm
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
# 下载股票数据
def download_stock_data(ticker, start_date, end_date):
data = yf.download(ticker, start=start_date, end=end_date)
return data
# 示例:下载苹果公司股票数据
stock_data = download_stock_data('AAPL', '2010-01-01', '2023-01-01')
2. 标记买卖点
我们需要定义买卖信号的标准。常见的方法包括:
基于未来价格变化:如果未来N天价格上涨X%,则标记为买入信号
基于技术指标交叉:如金叉/死叉
基于波动突破:突破一定波动范围时产生信号
def create_labels(data, window=5, threshold=0.02):
"""
创建买卖标签:
- 买入(1): 未来window天内价格上涨超过threshold
- 卖出(-1): 未来window天内价格下跌超过threshold
- 持有(0): 其他情况
"""
prices = data['Close']
future_prices = prices.shift(-window)
price_change = (future_prices - prices) / prices
labels = np.zeros(len(data))
labels[price_change > threshold] = 1 # 买入信号
labels[price_change < -threshold] = -1 # 卖出信号
# 删除最后window天的数据(没有未来价格)
labels = labels[:-window]
data = data.iloc[:-window]
return data, labels
3. 特征工程
构建技术指标作为SVM的输入特征:
python
复制
def create_features(data):
# 价格特征
data['Returns'] = data['Close'].pct_change()
data['SMA_10'] = data['Close'].rolling(window=10).mean()
data['SMA_30'] = data['Close'].rolling(window=30).mean()
# 波动率特征
data['Volatility'] = data['Returns'].rolling(window=10).std()
# 相对强弱指数(RSI)
delta = data['Close'].diff()
gain = delta.where(delta > 0, 0)
loss = -delta.where(delta < 0, 0)
avg_gain = gain.rolling(window=14).mean()
avg_loss = loss.rolling(window=14).mean()
rs = avg_gain / avg_loss
data['RSI'] = 100 - (100 / (1 + rs))
# MACD
exp12 = data['Close'].ewm(span=12, adjust=False).mean()
exp26 = data['Close'].ewm(span=26, adjust=False).mean()
data['MACD'] = exp12 - exp26
data['Signal_Line'] = data['MACD'].ewm(span=9, adjust=False).mean()
# 布林带
data['Upper_Bollinger'] = data['SMA_20'] + 2 * data['Close'].rolling(window=20).std()
data['Lower_Bollinger'] = data['SMA_20'] - 2 * data['Close'].rolling(window=20).std()
# 删除包含NaN的行
data = data.dropna()
return data
4. 模型训练与预测
python
复制
def train_svm_model(features, labels):
# 标准化特征
scaler = StandardScaler()
X = scaler.fit_transform(features)
y = labels
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, shuffle=False)
# 创建SVM模型
model = svm.SVC(kernel='rbf', C=1.0, gamma='scale')
# 训练模型
model.fit(X_train, y_train)
# 在测试集上评估
predictions = model.predict(X_test)
print(classification_report(y_test, predictions))
return model, scaler
# 准备数据
stock_data, labels = create_labels(stock_data)
features_data = create_features(stock_data)
features = features_data[['Returns', 'SMA_10', 'SMA_30', 'Volatility', 'RSI', 'MACD', 'Signal_Line', 'Upper_Bollinger', 'Lower_Bollinger']]
# 训练模型
model, scaler = train_svm_model(features, labels)
5. 交易策略回测
python
复制
def backtest_strategy(data, predictions):
"""
简单的回测策略:
- 当预测为买入信号时,第二天开盘买入
- 当预测为卖出信号时,第二天开盘卖出
- 计算累计收益
"""
data = data.copy()
data['Prediction'] = predictions
data['Position'] = 0 # 0: 无持仓, 1: 持有多头, -1: 持有空头
position = 0
portfolio_value = [10000] # 初始资金
for i in range(1, len(data)):
# 执行交易信号
if data['Prediction'].iloc[i-1] == 1 and position <= 0:
# 买入信号且当前无持仓或持有空头
position = 1
elif data['Prediction'].iloc[i-1] == -1 and position >= 0:
# 卖出信号且当前无持仓或持有多头
position = -1
# 计算当日收益
daily_return = (data['Close'].iloc[i] / data['Close'].iloc[i-1] - 1)
portfolio_value.append(portfolio_value[-1] * (1 + position * daily_return))
data['Portfolio_Value'] = portfolio_value
return data
# 在整个数据集上预测
X = scaler.transform(features)
all_predictions = model.predict(X)
# 回测策略
backtest_results = backtest_strategy(features_data, all_predictions)
# 绘制结果
import matplotlib.pyplot as plt
plt.figure(figsize=(12, 6))
plt.plot(backtest_results.index, backtest_results['Close'] / backtest_results['Close'].iloc[0], label='Buy and Hold')
plt.plot(backtest_results.index, backtest_results['Portfolio_Value'] / 10000, label='SVM Strategy')
plt.legend()
plt.title('Strategy Backtesting Results')
plt.show()
优化建议
- 特征选择:尝试不同的技术指标组合,使用特征重要性分析选择最有价值的特征
- 参数调优:使用网格搜索或贝叶斯优化调整SVM的C、gamma等参数
- 类别平衡:买卖信号可能不平衡,考虑使用class_weight参数或过采样/欠采样技术
- 多时间框架:结合不同时间周期的特征
- 集成方法:将SVM与其他模型结合使用
注意事项
- 股票市场具有高度随机性和不可预测性,任何模型都无法保证盈利
- 历史表现不代表未来结果,需谨慎评估策略风险
- 实际交易中需要考虑交易成本、滑点等因素
- 建议在模拟交易环境中充分测试后再投入实盘资金
通过这种方法,您可以建立一个基于SVM的股票买卖点预测系统,但请记住,金融市场预测极具挑战性,应结合风险管理和其他分析方法一起使用。
SVM股票买卖点预测系统开发(改进提示词)
你是一名资深软件工程师以及股票投资专家,请协助我完成向量机(SVM)预测股票买卖点的python编程。
第1步,数据收集。
获取国内A股数据,完成数据收集;需要获取股票的历史数据,涵盖开盘价、收盘价、最高价、最低价、成交量等信息。可以借助第三方库(如akshare, pandas-datareader等)来获取这些数据。
第2步,特征工程
对收集到的数据进行处理,提取出对股票买卖点有影响的特征。常见的特征有移动平均线、相对强弱指标(RSI)、布林带等。在特征选择上,可以尝试不同的技术指标组合,使用特征重要性分析选择最有价值的特征。并且,这些特征库可以继续添加或更新
第3步,标签买卖点
依据股票的历史数据,定义买卖点的标签。例如,当未来一段时间内股票价格上涨时,标签设为1(买入);当价格下跌时,标签设为 0(卖出)。或者,当指标触及RSI底部或布林带下轨底部或CCI底部时,设为买入,当当指标触及RSI顶部或布林带上轨顶部或CCI底部时,
第4步,数据划分
把处理好的数据划分为训练集和测试集,一般按照指定的比例划分,如80% 和 20% 。数据可结合不同时间周期的特征进行划分。
第5步,模型训练
运用训练集的数据对 SVM 模型进行训练。交易中可以考虑交易成本、滑点等因素,单独设置。
第6步,模型评估
使用测试集的数据对训练好的模型进行评估,计算模型的准确率、召回率等指标。对于参数调优:可以使用网格搜索或贝叶斯优化调整SVM的C、gamma等参数。对于类别平衡:买卖信号可能不平衡,考虑使用class_weight参数或过采样/欠采样技术。
第7步,预测买卖点
使用训练好的模型对新的数据进行预测,得到股票的买卖点。
SVM股票买卖点预测系统,下面是Deepseek基于SVM的股票买卖点预测系统,按照您提出的7个步骤进行开发。
第1步:数据收集
import akshare as ak
import pandas as pd
import numpy as np
from datetime import datetime, timedelta
def get_stock_data(stock_code, start_date, end_date):
"""
获取股票历史数据
:param stock_code: 股票代码,如 '600519' (贵州茅台)
:param start_date: 开始日期,格式 'YYYY-MM-DD'
:param end_date: 结束日期,格式 'YYYY-MM-DD'
:return: DataFrame包含股票历史数据
"""
try:
# 使用akshare获取A股数据
df = ak.stock_zh_a_hist(symbol=stock_code, period="daily", start_date=start_date, end_date=end_date)
# 重命名列以保持一致性
df = df.rename(columns={
'日期': 'date',
'开盘': 'open',
'收盘': 'close',
'最高': 'high',
'最低': 'low',
'成交量': 'volume',
'成交额': 'amount',
'振幅': 'amplitude',
'涨跌幅': 'pct_change',
'涨跌额': 'change_amount',
'换手率': 'turnover'
})
# 确保日期是datetime类型并按日期排序
df['date'] = pd.to_datetime(df['date'])
df = df.sort_values('date').reset_index(drop=True)
return df
except Exception as e:
print(f"获取数据失败: {e}")
return None
# 示例使用
end_date = datetime.now().strftime('%Y-%m-%d')
start_date = (datetime.now() - timedelta(days=365*5)).strftime('%Y-%m-%d') # 5年数据
stock_code = '600519' # 贵州茅台
stock_data = get_stock_data(stock_code, start_date, end_date)
print(stock_data.head())
第2步:特征工程
python
复制
import talib
from sklearn.preprocessing import StandardScaler
def calculate_technical_indicators(df):
"""
计算各种技术指标作为特征
:param df: 包含股票历史数据的DataFrame
:return: 添加了技术指标的DataFrame
"""
# 计算移动平均线
df['MA5'] = df['close'].rolling(window=5).mean()
df['MA10'] = df['close'].rolling(window=10).mean()
df['MA20'] = df['close'].rolling(window=20).mean()
df['MA60'] = df['close'].rolling(window=60).mean()
# 计算指数移动平均线
df['EMA12'] = talib.EMA(df['close'], timeperiod=12)
df['EMA26'] = talib.EMA(df['close'], timeperiod=26)
# 计算MACD
macd, macdsignal, macdhist = talib.MACD(df['close'], fastperiod=12, slowperiod=26, signalperiod=9)
df['MACD'] = macd
df['MACD_signal'] = macdsignal
df['MACD_hist'] = macdhist
# 计算RSI
df['RSI14'] = talib.RSI(df['close'], timeperiod=14)
df['RSI7'] = talib.RSI(df['close'], timeperiod=7)
# 计算布林带
upper, middle, lower = talib.BBANDS(df['close'], timeperiod=20, nbdevup=2, nbdevdn=2, matype=0)
df['BB_upper'] = upper
df['BB_middle'] = middle
df['BB_lower'] = lower
# 计算KDJ
df['K'], df['D'] = talib.STOCH(df['high'], df['low'], df['close'],
fastk_period=9, slowk_period=3,
slowk_matype=0, slowd_period=3, slowd_matype=0)
df['J'] = 3 * df['K'] - 2 * df['D']
# 计算CCI
df['CCI14'] = talib.CCI(df['high'], df['low'], df['close'], timeperiod=14)
# 计算ATR
df['ATR14'] = talib.ATR(df['high'], df['low'], df['close'], timeperiod=14)
# 计算OBV
df['OBV'] = talib.OBV(df['close'], df['volume'])
# 计算价格变化率
df['pct_change_5'] = df['close'].pct_change(5)
df['pct_change_10'] = df['close'].pct_change(10)
# 计算波动率
df['volatility_10'] = df['close'].pct_change().rolling(window=10).std()
# 填充NaN值
df = df.fillna(method='bfill').fillna(method='ffill')
return df
# 添加技术指标
stock_data_with_features = calculate_technical_indicators(stock_data)
# 标准化特征
def normalize_features(df, feature_columns):
"""
标准化特征数据
:param df: 包含特征的DataFrame
:param feature_columns: 需要标准化的特征列名列表
:return: 标准化后的DataFrame
"""
scaler = StandardScaler()
df[feature_columns] = scaler.fit_transform(df[feature_columns])
return df
# 定义特征列
feature_columns = [
'MA5', 'MA10', 'MA20', 'MA60',
'EMA12', 'EMA26',
'MACD', 'MACD_signal', 'MACD_hist',
'RSI14', 'RSI7',
'BB_upper', 'BB_middle', 'BB_lower',
'K', 'D', 'J',
'CCI14', 'ATR14', 'OBV',
'pct_change_5', 'pct_change_10',
'volatility_10'
]
# 标准化特征
stock_data_normalized = normalize_features(stock_data_with_features.copy(), feature_columns)
print(stock_data_normalized.head())
第3步:标签买卖点
python
复制
def create_labels(df, future_days=5, threshold=0.03):
"""
创建买卖点标签
:param df: 包含股票数据的DataFrame
:param future_days: 未来多少天的价格变化作为判断依据
:param threshold: 价格变化阈值,超过此阈值才标记为买卖点
:return: 包含标签的DataFrame
"""
# 计算未来N天的价格变化
future_pct = df['close'].pct_change(future_days).shift(-future_days)
# 创建标签
df['label'] = 0 # 0表示持有或不确定
df.loc[future_pct > threshold, 'label'] = 1 # 1表示买入信号
df.loc[future_pct < -threshold, 'label'] = -1 # -1表示卖出信号
# 删除最后future_days行,因为它们没有未来的价格数据
df = df[:-future_days]
return df
# 创建标签
stock_data_labeled = create_labels(stock_data_normalized.copy())
print(stock_data_labeled['label'].value_counts())
# 可视化标签分布
import matplotlib.pyplot as plt
plt.figure(figsize=(10, 6))
plt.plot(stock_data_labeled['date'], stock_data_labeled['close'], label='Close Price', alpha=0.5)
plt.scatter(stock_data_labeled[stock_data_labeled['label'] == 1]['date'],
stock_data_labeled[stock_data_labeled['label'] == 1]['close'],
color='green', label='Buy Signal', marker='^', alpha=1)
plt.scatter(stock_data_labeled[stock_data_labeled['label'] == -1]['date'],
stock_data_labeled[stock_data_labeled['label'] == -1]['close'],
color='red', label='Sell Signal', marker='v', alpha=1)
plt.title('Stock Price with Buy/Sell Signals')
plt.xlabel('Date')
plt.ylabel('Price')
plt.legend()
plt.show()
第4步:数据划分
python
复制
from sklearn.model_selection import train_test_split
def split_data(df, feature_columns, label_column, test_size=0.2):
"""
划分训练集和测试集
:param df: 包含特征和标签的DataFrame
:param feature_columns: 特征列名列表
:param label_column: 标签列名
:param test_size: 测试集比例
:return: X_train, X_test, y_train, y_test
"""
# 确保数据是按日期排序的
df = df.sort_values('date')
# 分割点
split_idx = int(len(df) * (1 - test_size))
# 按时间顺序划分
X_train = df[feature_columns].iloc[:split_idx]
X_test = df[feature_columns].iloc[split_idx:]
y_train = df[label_column].iloc[:split_idx]
y_test = df[label_column].iloc[split_idx:]
return X_train, X_test, y_train, y_test
# 划分数据
X_train, X_test, y_train, y_test = split_data(stock_data_labeled, feature_columns, 'label')
print(f"训练集大小: {len(X_train)}")
print(f"测试集大小: {len(X_test)}")
print(f"买入信号比例 - 训练集: {(y_train == 1).mean():.2f}, 测试集: {(y_test == 1).mean():.2f}")
print(f"卖出信号比例 - 训练集: {(y_train == -1).mean():.2f}, 测试集: {(y_test == -1).mean():.2f}")
第5步:模型训练
python
复制
from sklearn.svm import SVC
from sklearn.metrics import classification_report
from imblearn.over_sampling import SMOTE
def train_svm_model(X_train, y_train, C=1.0, gamma='scale', class_weight=None):
"""
训练SVM模型
:param X_train: 训练特征
:param y_train: 训练标签
:param C: SVM的C参数
:param gamma: SVM的gamma参数
:param class_weight: 类别权重
:return: 训练好的SVM模型
"""
# 处理类别不平衡问题 - 使用SMOTE过采样
smote = SMOTE(random_state=42)
X_train_res, y_train_res = smote.fit_resample(X_train, y_train)
# 初始化SVM模型
svm_model = SVC(kernel='rbf', C=C, gamma=gamma, class_weight=class_weight, random_state=42)
# 训练模型
svm_model.fit(X_train_res, y_train_res)
return svm_model
# 训练初始模型
svm_model = train_svm_model(X_train, y_train)
# 在训练集上的表现
train_pred = svm_model.predict(X_train)
print("训练集表现:")
print(classification_report(y_train, train_pred))
# 在测试集上的表现
test_pred = svm_model.predict(X_test)
print("测试集表现:")
print(classification_report(y_test, test_pred))
第6步:模型评估与参数调优
python
复制
from sklearn.model_selection import GridSearchCV
from sklearn.metrics import confusion_matrix, accuracy_score, f1_score
import seaborn as sns
def evaluate_model(model, X_test, y_test):
"""
评估模型表现
:param model: 训练好的模型
:param X_test: 测试特征
:param y_test: 测试标签
"""
# 预测
y_pred = model.predict(X_test)
# 计算指标
accuracy = accuracy_score(y_test, y_pred)
f1 = f1_score(y_test, y_pred, average='weighted')
print(f"准确率: {accuracy:.4f}")
print(f"F1分数: {f1:.4f}")
# 混淆矩阵
cm = confusion_matrix(y_test, y_pred)
plt.figure(figsize=(8, 6))
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues',
xticklabels=['Sell', 'Hold', 'Buy'],
yticklabels=['Sell', 'Hold', 'Buy'])
plt.title('Confusion Matrix')
plt.xlabel('Predicted')
plt.ylabel('Actual')
plt.show()
return accuracy, f1
# 评估初始模型
print("初始模型评估:")
initial_accuracy, initial_f1 = evaluate_model(svm_model, X_test, y_test)
def optimize_svm_parameters(X_train, y_train):
"""
使用网格搜索优化SVM参数
:param X_train: 训练特征
:param y_train: 训练标签
:return: 最佳模型
"""
# 定义参数网格
param_grid = {
'C': [0.1, 1, 10, 100],
'gamma': ['scale', 'auto', 0.1, 1, 10],
'class_weight': [None, 'balanced', {-1: 2, 0: 1, 1: 2}]
}
# 使用SMOTE处理不平衡数据
smote = SMOTE(random_state=42)
X_train_res, y_train_res = smote.fit_resample(X_train, y_train)
# 初始化网格搜索
grid_search = GridSearchCV(
SVC(kernel='rbf', random_state=42),
param_grid,
cv=5,
scoring='f1_weighted',
n_jobs=-1,
verbose=1
)
# 执行网格搜索
grid_search.fit(X_train_res, y_train_res)
# 输出最佳参数
print("最佳参数:", grid_search.best_params_)
return grid_search.best_estimator_
# 参数优化 (可能需要较长时间)
# best_svm_model = optimize_svm_parameters(X_train, y_train)
# 为了演示,我们手动设置一组较好的参数
best_svm_model = train_svm_model(X_train, y_train, C=10, gamma=0.1, class_weight='balanced')
# 评估优化后的模型
print("优化后模型评估:")
optimized_accuracy, optimized_f1 = evaluate_model(best_svm_model, X_test, y_test)
# 比较模型表现
improvement = (optimized_accuracy - initial_accuracy) / initial_accuracy * 100
print(f"准确率提升: {improvement:.2f}%")
第7步:预测买卖点
python
复制
def predict_signals(model, df, feature_columns):
"""
使用模型预测买卖信号
:param model: 训练好的模型
:param df: 包含特征的DataFrame
:param feature_columns: 特征列名列表
:return: 添加了预测信号的DataFrame
"""
# 确保数据是按日期排序的
df = df.sort_values('date')
# 预测信号
signals = model.predict(df[feature_columns])
# 添加预测信号到DataFrame
df['predicted_signal'] = signals
return df
# 预测信号
stock_data_with_signals = predict_signals(best_svm_model, stock_data_labeled, feature_columns)
# 可视化预测信号
plt.figure(figsize=(14, 8))
plt.plot(stock_data_with_signals['date'], stock_data_with_signals['close'], label='Close Price', alpha=0.5)
# 实际信号
plt.scatter(stock_data_with_signals[stock_data_with_signals['label'] == 1]['date'],
stock_data_with_signals[stock_data_with_signals['label'] == 1]['close'],
color='green', label='Actual Buy', marker='^', alpha=0.5)
plt.scatter(stock_data_with_signals[stock_data_with_signals['label'] == -1]['date'],
stock_data_with_signals[stock_data_with_signals['label'] == -1]['close'],
color='red', label='Actual Sell', marker='v', alpha=0.5)
# 预测信号
plt.scatter(stock_data_with_signals[stock_data_with_signals['predicted_signal'] == 1]['date'],
stock_data_with_signals[stock_data_with_signals['predicted_signal'] == 1]['close'],
color='blue', label='Predicted Buy', marker='^', alpha=1)
plt.scatter(stock_data_with_signals[stock_data_with_signals['predicted_signal'] == -1]['date'],
stock_data_with_signals[stock_data_with_signals['predicted_signal'] == -1]['close'],
color='orange', label='Predicted Sell', marker='v', alpha=1)
plt.title('Stock Price with Actual and Predicted Signals')
plt.xlabel('Date')
plt.ylabel('Price')
plt.legend()
plt.show()
def backtest_strategy(df, initial_capital=100000, commission=0.001):
"""
回测交易策略
:param df: 包含预测信号的DataFrame
:param initial_capital: 初始资金
:param commission: 交易佣金比例
:return: 回测结果
"""
capital = initial_capital
position = 0 # 0表示空仓,1表示持仓
buy_price = 0
trades = []
for i in range(len(df)):
current_price = df.iloc[i]['close']
signal = df.iloc[i]['predicted_signal']
# 买入信号且当前空仓
if signal == 1 and position == 0:
position = 1
buy_price = current_price
shares = capital * (1 - commission) / buy_price
capital = 0
trades.append({
'date': df.iloc[i]['date'],
'type': 'buy',
'price': buy_price,
'shares': shares
})
# 卖出信号且当前持仓
elif signal == -1 and position == 1:
position = 0
sell_price = current_price
capital = shares * sell_price * (1 - commission)
trades.append({
'date': df.iloc[i]['date'],
'type': 'sell',
'price': sell_price,
'shares': shares
})
shares = 0
# 计算最终资产
if position == 1:
final_value = shares * df.iloc[-1]['close'] * (1 - commission)
else:
final_value = capital
# 计算基准表现 (买入并持有)
benchmark = (df.iloc[-1]['close'] / df.iloc[0]['close']) * initial_capital * (1 - commission)
return {
'final_value': final_value,
'return': (final_value - initial_capital) / initial_capital * 100,
'benchmark_return': (benchmark - initial_capital) / initial_capital * 100,
'trades': trades
}
# 回测策略
backtest_result = backtest_strategy(stock_data_with_signals)
print(f"策略最终价值: {backtest_result['final_value']:.2f}")
print(f"策略收益率: {backtest_result['return']:.2f}%")
print(f"基准收益率: {backtest_result['benchmark_return']:.2f}%")
print(f"交易次数: {len(backtest_result['trades']) // 2}")
#完整系统集成
class StockTradingSVM:
"""
基于SVM的股票交易系统
"""
def __init__(self, stock_code, start_date, end_date):
self.stock_code = stock_code
self.start_date = start_date
self.end_date = end_date
self.data = None
self.model = None
self.feature_columns = [
'MA5', 'MA10', 'MA20', 'MA60',
'EMA12', 'EMA26',
'MACD', 'MACD_signal', 'MACD_hist',
'RSI14', 'RSI7',
'BB_upper', 'BB_middle', 'BB_lower',
'K', 'D', 'J',
'CCI14', 'ATR14', 'OBV',
'pct_change_5', 'pct_change_10',
'volatility_10'
]
def load_data(self):
"""加载股票数据"""
self.data = get_stock_data(self.stock_code, self.start_date, self.end_date)
if self.data is not None:
print(f"成功加载 {len(self.data)} 条数据")
else:
print("数据加载失败")
def preprocess_data(self):
"""数据预处理"""
if self.data is not None:
# 计算技术指标
self.data = calculate_technical_indicators(self.data)
# 标准化特征
self.data = normalize_features(self.data, self.feature_columns)
# 创建标签
self.data = create_labels(self.data)
print("数据预处理完成")
else:
print("请先加载数据")
def train_model(self):
"""训练模型"""
if self.data is not None:
# 划分数据
X_train, X_test, y_train, y_test = split_data(self.data, self.feature_columns, 'label')
# 训练模型
self.model = train_svm_model(X_train, y_train, C=10, gamma=0.1, class_weight='balanced')
# 评估模型
print("模型训练完成,测试集表现:")
evaluate_model(self.model, X_test, y_test)
else:
print("请先预处理数据")
def predict_and_backtest(self):
"""预测并回测"""
if self.model is not None and self.data is not None:
# 预测信号
self.data = predict_signals(self.model, self.data, self.feature_columns)
# 回测
result = backtest_strategy(self.data)
print("\n回测结果:")
print(f"策略最终价值: {result['final_value']:.2f}")
print(f"策略收益率: {result['return']:.2f}%")
print(f"基准收益率: {result['benchmark_return']:.2f}%")
print(f"交易次数: {len(result['trades']) // 2}")
# 可视化
self.visualize_signals()
else:
print("请先训练模型")
def visualize_signals(self):
"""可视化信号"""
if self.data is not None:
plt.figure(figsize=(14, 8))
plt.plot(self.data['date'], self.data['close'], label='Close Price', alpha=0.5)
# 预测信号
plt.scatter(self.data[self.data['predicted_signal'] == 1]['date'],
self.data[self.data['predicted_signal'] == 1]['close'],
color='blue', label='Predicted Buy', marker='^', alpha=1)
plt.scatter(self.data[self.data['predicted_signal'] == -1]['date'],
self.data[self.data['predicted_signal'] == -1]['close'],
color='orange', label='Predicted Sell', marker='v', alpha=1)
plt.title('Stock Price with Predicted Signals')
plt.xlabel('Date')
plt.ylabel('Price')
plt.legend()
plt.show()
else:
print("没有可用的数据进行可视化")
# 使用完整系统
trading_system = StockTradingSVM(
stock_code='600519', # 贵州茅台
start_date='2018-01-01',
end_date='2023-12-31'
)
# 执行完整流程
trading_system.load_data()
trading_system.preprocess_data()
trading_system.train_model()
trading_system.predict_and_backtest()
总结与改进建议
这个基于SVM的股票交易系统实现了您要求的全部7个步骤。以下是系统的主要特点和可能的改进方向:
系统特点:
完整的数据获取、预处理、特征工程流程
使用多种技术指标作为特征
考虑了类别不平衡问题,使用SMOTE过采样
包含模型评估和参数优化
实现了回测功能,可以评估策略表现
改进建议:
特征工程:可以尝试添加更多技术指标或基本面数据
标签定义:可以尝试不同的买卖点定义方法,如基于波动率或成交量
模型集成:可以尝试结合多个模型或使用集成学习方法
交易成本:可以更精细地模拟交易成本、滑点等实际交易因素
风险管理:可以添加止损、止盈等风险管理策略
以下是豆包的代码:
import akshare as ak
import pandas as pd
import numpy as np
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.metrics import accuracy_score, recall_score
from sklearn.preprocessing import StandardScaler
from imblearn.over_sampling import SMOTE
# 第1步:数据收集
def get_stock_data(stock_code, start_date, end_date):
stock_df = ak.stock_zh_a_hist(symbol=stock_code, period="daily", start_date=start_date, end_date=end_date)
stock_df.columns = ['日期', '开盘', '收盘', '最高', '最低', '成交量', '成交额', '振幅', '涨跌幅', '涨跌额', '换手率']
return stock_df
# 第2步:特征工程
def feature_engineering(data):
# 计算移动平均线
data['MA5'] = data['收盘'].rolling(window=5).mean()
data['MA10'] = data['收盘'].rolling(window=10).mean()
# 计算相对强弱指标(RSI)
delta = data['收盘'].diff()
up = delta.clip(lower=0)
down = -delta.clip(upper=0)
avg_gain = up.rolling(window=14).mean()
avg_loss = down.rolling(window=14).mean()
rs = avg_gain / avg_loss
data['RSI'] = 100 - (100 / (1 + rs))
# 计算布林带
data['STD'] = data['收盘'].rolling(window=20).std()
data['Upper'] = data['MA10'] + 2 * data['STD']
data['Lower'] = data['MA10'] - 2 * data['STD']
data = data.dropna()
return data
# 第3步:标签买卖点
def label_buy_sell_points(data, future_period=5):
data['未来收盘价'] = data['收盘'].shift(-future_period)
data['标签'] = np.where(data['未来收盘价'] > data['收盘'], 1, 0)
data = data.dropna()
return data
# 第4步:数据划分
def split_data(data, features, target, test_size=0.2):
X = data[features]
y = data[target]
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=test_size, random_state=42)
return X_train, X_test, y_train, y_test
# 第5步:模型训练
def train_svm_model(X_train, y_train):
# 数据标准化
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
# 处理类别不平衡
smote = SMOTE(random_state=42)
X_train_resampled, y_train_resampled = smote.fit_resample(X_train_scaled, y_train)
# 参数调优
param_grid = {'C': [0.1, 1, 10], 'gamma': [0.001, 0.01, 0.1]}
grid_search = GridSearchCV(SVC(), param_grid, cv=5)
grid_search.fit(X_train_resampled, y_train_resampled)
best_model = grid_search.best_estimator_
return best_model, scaler
# 第6步:模型评估
def evaluate_model(model, X_test, y_test, scaler):
X_test_scaled = scaler.transform(X_test)
y_pred = model.predict(X_test_scaled)
accuracy = accuracy_score(y_test, y_pred)
recall = recall_score(y_test, y_pred)
print(f"准确率: {accuracy}")
print(f"召回率: {recall}")
# 第7步:预测买卖点
def predict_buy_sell_points(model, new_data, scaler, features):
new_X = new_data[features]
new_X_scaled = scaler.transform(new_X)
predictions = model.predict(new_X_scaled)
new_data['预测标签'] = predictions
return new_data
if __name__ == "__main__":
stock_code = "600519" # 茅台股票代码
start_date = "20200101"
end_date = "20231231"
# 数据收集
stock_data = get_stock_data(stock_code, start_date, end_date)
# 特征工程
feature_data = feature_engineering(stock_data)
# 标签买卖点
labeled_data = label_buy_sell_points(feature_data)
# 选择特征和目标
features = ['开盘', '收盘', '最高', '最低', '成交量', 'MA5', 'MA10', 'RSI', 'Upper', 'Lower']
target = '标签'
# 数据划分
X_train, X_test, y_train, y_test = split_data(labeled_data, features, target)
# 模型训练
model, scaler = train_svm_model(X_train, y_train)
# 模型评估
evaluate_model(model, X_test, y_test, scaler)
# 预测买卖点
new_predictions = predict_buy_sell_points(model, labeled_data, scaler, features)
print(new_predictions[['日期', '预测标签']])
这个系统提供了一个良好的起点,您可以根据实际需求进一步调整和优化。
浙公网安备 33010602011771号