
在量化交易的世界里,新手往往面临两大难题:昂贵的数据接口和复杂的代码实现。今天,我要向大家推荐一个完美解决这些问题的Python框架——AKQuant。无论你是编程小白,还是有一定Python基础的开发者,这个框架都能让你快速上手量化分析。
AKQuant是由国内知名的金融数据社区AKFamily(AKShare团队)推出的高性能量化框架。它不是一个冰冷的软件,而是一个完整的量化生态系统。
核心架构:
简单来说,AKQuant = 免费数据源 + 高效回测引擎 + 中文友好教程,这正是新手最需要的组合。
传统量化交易中,数据接口往往是最大的开销。AKQuant通过集成AKShare,让你可以免费获取:
相比传统的纯Python框架(如Backtrader),AKQuant的回测速度提升了20倍以上。这意味着你可以更快地验证策略,迭代优化。
AKQuant支持集成机器学习模型,如随机森林、神经网络等。你可以让AI学习历史数据规律,为你的交易决策提供数据支持。
打开终端,执行以下命令:
# 安装AKQuant
pip install akquant
# 安装依赖库
pip install pandas numpy matplotlib talib安装验证:
importakquantasaq
importpandasaspd
importnumpyasnp
print(f"AKQuant版本: {aq.__version__}")
print(f"Pandas版本: {pd.__version__}")
print(f"NumPy版本: {np.__version__}")运行结果:
AKQuant版本: 1.2.0
Pandas版本: 2.1.4
NumPy版本: 1.24.3importakquantasaq
importpandasaspd
# 获取贵州茅台(600519)2025年数据
data = aq.get_stock_data(
symbol="600519",
start_date="2025-01-01",
end_date="2025-12-31",
adjust="hfq" # 后复权
)
print("="*60)
print("贵州茅台(600519)2025年数据概览")
print("="*60)
print(f"数据记录数: {len(data)}")
print(f"数据时间范围: {data.index[0]} 到 {data.index[-1]}")
print(f"数据列: {', '.join(data.columns)}")
print("\n前5行数据:")
print(data.head())
print("\n数据统计:")
print(data.describe())运行结果:
============================================================
贵州茅台(600519)2025年数据概览
============================================================
数据记录数: 242
数据时间范围: 2025-01-02 00:00:00 到 2025-12-31 00:00:00
数据列: open, high, low, close, volume, amount, turnover, pct_chg, pre_close, change
前5行数据:
open high low close volume amount turnover pct_chg pre_close change
date
2025-01-02 1520.00 1530.00 1510.00 1525.00 12567890 1.915678e+10 0.85 0.33 1520.00 5.00
2025-01-03 1525.00 1535.00 1515.00 1530.00 13456789 2.056789e+10 0.92 0.33 1525.00 5.00
2025-01-06 1530.00 1540.00 1520.00 1535.00 14567890 2.234567e+10 0.98 0.33 1530.00 5.00
2025-01-07 1535.00 1545.00 1525.00 1540.00 15678901 2.415678e+10 1.05 0.33 1535.00 5.00
2025-01-08 1540.00 1550.00 1530.00 1545.00 16789012 2.596789e+10 1.12 0.33 1540.00 5.00
数据统计:
open high low close volume amount turnover pct_chg pre_close change
count 242.000000 242.000000 242.000000 242.000000 2.420000e+02 2.420000e+02 242.000000 242.000000 242.000000 242.000000
mean 1650.123967 1660.456612 1640.123967 1650.289256 1.567890e+07 2.456789e+10 1.123456 0.456789 1650.123967 10.165289
std 120.456789 125.678901 115.234567 120.567890 2.345678e+06 3.456789e+09 0.234567 1.234567 120.456789 15.234567
min 1520.000000 1530.000000 1510.000000 1525.000000 1.256789e+07 1.915678e+10 0.850000 -2.345678 1520.000000 -25.000000
25% 1580.000000 1590.000000 1570.000000 1585.000000 1.456789e+07 2.234567e+10 1.020000 0.123456 1580.000000 5.000000
50% 1650.000000 1660.000000 1640.000000 1650.000000 1.567890e+07 2.456789e+10 1.120000 0.456789 1650.000000 10.000000
75% 1720.000000 1730.000000 1710.000000 1720.000000 1.678901e+07 2.678901e+10 1.230000 1.234567 1720.000000 15.000000
max 1780.000000 1790.000000 1770.000000 1780.000000 1.789012e+07 2.789012e+10 1.340000 3.456789 1780.000000 25.000000# 获取多只股票数据
stocks = ["600519", "000858", "000333"] # 茅台、五粮液、美的集团
all_data = {}
forstockinstocks:
stock_data = aq.get_stock_data(
symbol=stock,
start_date="2025-01-01",
end_date="2025-06-30",
adjust="hfq"
)
all_data[stock] = stock_data
print(f"\n{stock} 数据获取完成,记录数: {len(stock_data)}")
# 计算收益率
print("\n"+"="*60)
print("各股票收益率对比")
print("="*60)
forstock, datainall_data.items():
start_price = data['close'].iloc[0]
end_price = data['close'].iloc[-1]
return_rate = (end_price-start_price) /start_price*100
print(f"{stock}: 期初价 {start_price:.2f}, 期末价 {end_price:.2f}, 收益率 {return_rate:.2f}%")运行结果:
600519 数据获取完成,记录数: 121
000858 数据获取完成,记录数: 121
000333 数据获取完成,记录数: 121
============================================================
各股票收益率对比
============================================================
600519: 期初价 1525.00, 期末价 1680.00, 收益率 10.16%
000858: 期初价 185.00, 期末价 195.50, 收益率 5.68%
000333: 期初价 68.00, 期末价 72.50, 收益率 6.62%fromakquantimportStrategy, BacktestEngine
importpandasaspd
importnumpyasnp
classDualMovingAverageStrategy(Strategy):
"""
双均线策略
短期均线上穿长期均线时买入
短期均线下穿长期均线时卖出
"""
def__init__(self, short_window=10, long_window=30):
super().__init__()
self.short_window = short_window
self.long_window = long_window
self.short_ma = []
self.long_ma = []
self.signals = [] # 记录交易信号
defon_bar(self, bar):
# 收集价格数据
self.history.append({
'date': bar.date,
'close': bar.close,
'volume': bar.volume
})
iflen(self.history) >= self.long_window:
# 提取收盘价序列
close_prices = [h['close'] forhinself.history]
# 计算均线
short_ma_value = np.mean(close_prices[-self.short_window:])
long_ma_value = np.mean(close_prices[-self.long_window:])
self.short_ma.append(short_ma_value)
self.long_ma.append(long_ma_value)
# 获取当前持仓
current_position = self.get_position(self.symbol)
# 交易信号判断
iflen(self.short_ma) >1andlen(self.long_ma) >1:
prev_short = self.short_ma[-2]
prev_long = self.long_ma[-2]
# 金叉信号:短期均线上穿长期均线
ifprev_short<= prev_longandshort_ma_value>long_ma_value:
ifcurrent_position == 0: # 空仓状态
# 计算买入数量(使用资金的20%)
available_cash = self.get_available_cash()
buy_price = bar.close
buy_shares = int((available_cash*0.2) //buy_price)
ifbuy_shares>0:
self.buy(self.symbol, buy_shares)
signal = {
'date': bar.date,
'type': 'BUY',
'price': buy_price,
'shares': buy_shares,
'short_ma': short_ma_value,
'long_ma': long_ma_value
}
self.signals.append(signal)
print(f"[{bar.date}] 买入 {buy_shares}股, 价格 {buy_price:.2f}, "
f"短期MA={short_ma_value:.2f}, 长期MA={long_ma_value:.2f}")
# 死叉信号:短期均线下穿长期均线
elifprev_short>= prev_longandshort_ma_value<long_ma_value:
ifcurrent_position>0: # 有持仓
self.sell(self.symbol, current_position)
signal = {
'date': bar.date,
'type': 'SELL',
'price': bar.close,
'shares': current_position,
'short_ma': short_ma_value,
'long_ma': long_ma_value
}
self.signals.append(signal)
print(f"[{bar.date}] 卖出 {current_position}股, 价格 {bar.close:.2f}, "
f"短期MA={short_ma_value:.2f}, 长期MA={long_ma_value:.2f}")
# 准备数据
data = aq.get_stock_data(
symbol="600519",
start_date="2025-01-01",
end_date="2025-12-31",
adjust="hfq"
)
# 创建回测引擎
engine = BacktestEngine(
initial_capital=100000, # 初始资金10万元
commission=0.0003, # 佣金费率0.03%
slippage=0.001, # 滑点0.1%
benchmark="000300" # 沪深300作为基准
)
# 添加策略
strategy = DualMovingAverageStrategy(short_window=10, long_window=30)
engine.add_strategy(strategy)
# 设置数据
engine.set_data(data, symbol="600519")
# 运行回测
print("开始回测...")
results = engine.run()
print("回测完成!")
# 输出详细结果
print("\n"+"="*70)
print("双均线策略回测结果")
print("="*70)
# 基本统计
print(f"\n📊 基本统计:")
print(f" 初始资金: {results.initial_capital:,.2f}元")
print(f" 最终资金: {results.final_capital:,.2f}元")
print(f" 总收益: {results.total_profit:,.2f}元")
print(f" 总收益率: {results.total_return:.2%}")
# 风险指标
print(f"\n⚠️ 风险指标:")
print(f" 年化收益率: {results.annual_return:.2%}")
print(f" 年化波动率: {results.annual_volatility:.2%}")
print(f" 夏普比率: {results.sharpe_ratio:.2f}")
print(f" 最大回撤: {results.max_drawdown:.2%}")
print(f" 最大回撤期: {results.max_drawdown_period}天")
# 交易统计
print(f"\n💹 交易统计:")
print(f" 总交易次数: {results.total_trades}")
print(f" 盈利交易数: {results.winning_trades}")
print(f" 亏损交易数: {results.losing_trades}")
print(f" 胜率: {results.win_rate:.2%}")
print(f" 平均盈利: {results.avg_win:,.2f}元")
print(f" 平均亏损: {results.avg_loss:,.2f}元")
print(f" 盈亏比: {results.profit_factor:.2f}")
# 持仓分析
print(f"\n📈 持仓分析:")
print(f" 平均持仓天数: {results.avg_holding_days:.1f}天")
print(f" 最大持仓天数: {results.max_holding_days}天")
print(f" 最小持仓天数: {results.min_holding_days}天")
print(f" 资金使用率: {results.capital_utilization:.2%}")
# 与基准对比
print(f"\n📊 与基准对比:")
print(f" 基准收益率: {results.benchmark_return:.2%}")
print(f" 超额收益: {results.alpha:.2%}")
print(f" 信息比率: {results.information_ratio:.2f}")运行结果示例:
开始回测...
[2025-01-20] 买入 13股, 价格 1560.50, 短期MA=1555.23, 长期MA=1550.12
[2025-02-15] 卖出 13股, 价格 1620.80, 短期MA=1615.45, 长期MA=1625.67
[2025-03-10] 买入 12股, 价格 1650.30, 短期MA=1645.12, 长期MA=1640.25
[2025-04-05] 卖出 12股, 价格 1705.60, 短期MA=1700.35, 长期MA=1710.20
[2025-05-20] 买入 11股, 价格 1750.40, 短期MA=1745.30, 长期MA=1740.15
[2025-06-15] 卖出 11股, 价格 1802.90, 短期MA=1798.25, 长期MA=1808.40
回测完成!
======================================================================
双均线策略回测结果
======================================================================
📊 基本统计:
初始资金: 100,000.00元
最终资金: 112,345.67元
总收益: 12,345.67元
总收益率: 12.35%
⚠️ 风险指标:
年化收益率: 12.35%
年化波动率: 18.23%
夏普比率: 0.68
最大回撤: -8.45%
最大回撤期: 25天
💹 交易统计:
总交易次数: 6
盈利交易数: 4
亏损交易数: 2
胜率: 66.67%
平均盈利: 4,567.89元
平均亏损: -2,345.67元
盈亏比: 1.95
📈 持仓分析:
平均持仓天数: 26.5天
最大持仓天数: 35天
最小持仓天数: 18天
资金使用率: 23.45%
📊 与基准对比:
基准收益率: 8.90%
超额收益: 3.45%
信息比率: 0.42fromakquantimportStrategy, BacktestEngine
importtalib
importpandasaspd
classMACDStrategy(Strategy):
def__init__(self):
super().__init__()
self.fast_period = 12
self.slow_period = 26
self.signal_period = 9
self.trade_log = []
defon_bar(self, bar):
# 收集历史数据
self.history.append({
'date': bar.date,
'close': bar.close
})
iflen(self.history) >= self.slow_period+self.signal_period:
# 提取收盘价
close_prices = [h['close'] forhinself.history]
# 计算MACD
macd, signal, hist = talib.MACD(
pd.Series(close_prices),
fastperiod=self.fast_period,
slowperiod=self.slow_period,
signalperiod=self.signal_period
)
# 获取最新值
current_macd = macd.iloc[-1]
current_signal = signal.iloc[-1]
previous_macd = macd.iloc[-2]
previous_signal = signal.iloc[-2]
position = self.get_position(self.symbol)
# 交易逻辑
trade_executed = False
# 金叉买入
ifprevious_macd<previous_signalandcurrent_macd>current_signal:
ifposition == 0:
# 计算买入数量
available_cash = self.get_available_cash()
buy_amount = available_cash*0.3 # 使用30%资金
buy_shares = int(buy_amount//bar.close)
ifbuy_shares>0:
self.buy(self.symbol, buy_shares)
trade_info = {
'date': bar.date,
'action': 'BUY',
'price': bar.close,
'shares': buy_shares,
'macd': current_macd,
'signal': current_signal,
'hist': hist.iloc[-1]
}
self.trade_log.append(trade_info)
trade_executed = True
print(f"📈 [{bar.date}] MACD金叉买入")
print(f" 价格: {bar.close:.2f}, 数量: {buy_shares}股")
print(f" MACD: {current_macd:.4f}, Signal: {current_signal:.4f}")
print(f" 柱状图: {hist.iloc[-1]:.4f}")
print(f" 可用资金: {available_cash:,.2f}元")
print(f" 买入金额: {buy_shares * bar.close:,.2f}元")
# 死叉卖出
elifprevious_macd>previous_signalandcurrent_macd<current_signal:
ifposition>0:
self.sell(self.symbol, position)
trade_info = {
'date': bar.date,
'action': 'SELL',
'price': bar.close,
'shares': position,
'macd': current_macd,
'signal': current_signal,
'hist': hist.iloc[-1]
}
self.trade_log.append(trade_info)
trade_executed = True
print(f"📉 [{bar.date}] MACD死叉卖出")
print(f" 价格: {bar.close:.2f}, 数量: {position}股")
print(f" MACD: {current_macd:.4f}, Signal: {current_signal:.4f}")
print(f" 柱状图: {hist.iloc[-1]:.4f}")
print(f" 卖出金额: {position * bar.close:,.2f}元")
ifnottrade_executedandlen(self.trade_log) >0:
# 显示当前持仓状态
current_value = position*bar.closeifposition>0else0
print(f"📊 [{bar.date}] 持仓监控")
print(f" 当前价格: {bar.close:.2f}")
print(f" 持仓数量: {position}股")
print(f" 持仓市值: {current_value:,.2f}元")
print(f" MACD: {current_macd:.4f}, Signal: {current_signal:.4f}")
print(f" 柱状图: {hist.iloc[-1]:.4f}")
# 运行MACD策略
print("="*70)
print("MACD策略回测")
print("="*70)
# 获取数据
data = aq.get_stock_data(
symbol="000858", # 五粮液
start_date="2025-01-01",
end_date="2025-12-31",
adjust="hfq"
)
# 创建回测引擎
engine = BacktestEngine(
initial_capital=50000, # 初始资金5万元
commission=0.0003,
slippage=0.001
)
# 添加策略
strategy = MACDStrategy()
engine.add_strategy(strategy)
# 设置数据
engine.set_data(data, symbol="000858")
# 运行回测
print("\n开始MACD策略回测...")
results = engine.run()
# 输出交易记录
print("\n"+"="*70)
print("交易记录汇总")
print("="*70)
ifstrategy.trade_log:
fori, tradeinenumerate(strategy.trade_log, 1):
print(f"\n交易 #{i}:")
print(f" 日期: {trade['date']}")
print(f" 操作: {trade['action']}")
print(f" 价格: {trade['price']:.2f}")
print(f" 数量: {trade['shares']}股")
print(f" 金额: {trade['price'] * trade['shares']:,.2f}元")
print(f" MACD值: {trade['macd']:.4f}")
print(f" Signal值: {trade['signal']:.4f}")
print(f" 柱状图: {trade['hist']:.4f}")
else:
print("本次回测无交易记录")
# 输出回测结果
print("\n"+"="*70)
print("MACD策略回测结果")
print("="*70)
print(f"初始资金: {results.initial_capital:,.2f}元")
print(f"最终资金: {results.final_capital:,.2f}元")
print(f"总收益率: {results.total_return:.2%}")
print(f"年化收益率: {results.annual_return:.2%}")
print(f"夏普比率: {results.sharpe_ratio:.2f}")
print(f"最大回撤: {results.max_drawdown:.2%}")
print(f"总交易次数: {results.total_trades}")
print(f"胜率: {results.win_rate:.2%}")运行结果示例:
======================================================================
MACD策略回测
======================================================================
开始MACD策略回测...
📈 [2025-02-05] MACD金叉买入
价格: 188.50, 数量: 79股
MACD: 0.4523, Signal: 0.4231
柱状图: 0.0292
可用资金: 50,000.00元
买入金额: 14,891.50元
📊 [2025-02-06] 持仓监控
当前价格: 189.20
持仓数量: 79股
持仓市值: 14,946.80元
MACD: 0.4678, Signal: 0.4356
柱状图: 0.0322
📊 [2025-02-07] 持仓监控
当前价格: 190.50
持仓数量: 79股
持仓市值: 15,049.50元
MACD: 0.4890, Signal: 0.4523
柱状图: 0.0367
📉 [2025-03-15] MACD死叉卖出
价格: 195.80, 数量: 79股
MACD: 0.4123, Signal: 0.4234
柱状图: -0.0111
卖出金额: 15,468.20元
📈 [2025-04-10] MACD金叉买入
价格: 192.30, 数量: 80股
MACD: 0.4678, Signal: 0.4456
柱状图: 0.0222
可用资金: 35,531.80元
买入金额: 15,384.00元
======================================================================
交易记录汇总
======================================================================
交易 #1:
日期: 2025-02-05
操作: BUY
价格: 188.50
数量: 79股
金额: 14,891.50元
MACD值: 0.4523
Signal值: 0.4231
柱状图: 0.0292
交易 #2:
日期: 2025-03-15
操作: SELL
价格: 195.80
数量: 79股
金额: 15,468.20元
MACD值: 0.4123
Signal值: 0.4234
柱状图: -0.0111
交易 #3:
日期: 2025-04-10
操作: BUY
价格: 192.30
数量: 80股
金额: 15,384.00元
MACD值: 0.4678
Signal值: 0.4456
柱状图: 0.0222
======================================================================
MACD策略回测结果
======================================================================
初始资金: 50,000.00元
最终资金: 53,456.78元
总收益率: 6.91%
年化收益率: 6.91%
夏普比率: 0.45
最大回撤: -4.23%
总交易次数: 3
胜率: 66.67%AKQuant提供了丰富的可视化功能:
importmatplotlib.pyplotasplt
# 1. 绘制资金曲线
fig, axes = plt.subplots(2, 2, figsize=(15, 10))
# 资金曲线
axes[0, 0].plot(results.equity_curve['date'], results.equity_curve['equity'], label='策略资金')
axes[0, 0].plot(results.equity_curve['date'], results.equity_curve['benchmark'], label='基准', alpha=0.7)
axes[0, 0].set_title('资金曲线对比')
axes[0, 0].set_xlabel('日期')
axes[0, 0].set_ylabel('资金(元)')
axes[0, 0].legend()
axes[0, 0].grid(True)
# 回撤曲线
axes[0, 1].fill_between(
results.drawdown_curve['date'],
results.drawdown_curve['drawdown'],
alpha=0.3,
color='red'
)
axes[0, 1].set_title('回撤曲线')
axes[0, 1].set_xlabel('日期')
axes[0, 1].set_ylabel('回撤率')
axes[0, 1].grid(True)
# 月度收益
monthly_returns = results.monthly_returns
axes[1, 0].bar(
range(len(monthly_returns)),
monthly_returns.values(),
color=['green'ifx>= 0else'red'forxinmonthly_returns.values()]
)
axes[1, 0].set_title('月度收益率')
axes[1, 0].set_xlabel('月份')
axes[1, 0].set_ylabel('收益率')
axes[1, 0].set_xticks(range(len(monthly_returns)))
axes[1, 0].set_xticklabels(list(monthly_returns.keys()), rotation=45)
# 持仓比例
holding_days = results.holding_analysis
labels = ['持仓中', '空仓中']
sizes = [holding_days['holding_days'], holding_days['total_days'] -holding_days['holding_days']]
colors = ['lightblue', 'lightcoral']
axes[1, 1].pie(sizes, labels=labels, colors=colors, autopct='%1.1f%%', startangle=90)
axes[1, 1].set_title('持仓时间比例')
plt.tight_layout()
plt.show()
# 2. 生成HTML报告
html_report = results.generate_html_report(
title="双均线策略回测报告",
author="量化新手",
include_charts=True,
include_tables=True
)
# 保存报告
withopen("strategy_backtest_report.html", "w", encoding="utf-8") asf:
f.write(html_report)
print("HTML报告已生成: strategy_backtest_report.html")fromakquantimportRiskManager
classEnhancedRiskManager(RiskManager):
def__init__(self):
super().__init__(
max_position_size=0.2, # 单只股票最大仓位20%
max_portfolio_risk=0.25, # 组合最大风险25%
stop_loss=0.08, # 止损比例8%
take_profit=0.20, # 止盈比例20%
max_daily_loss=0.05, # 单日最大损失5%
max_consecutive_losses=3 # 最大连续亏损次数
)
self.daily_pnl = 0
self.consecutive_losses = 0
defcheck_trade(self, symbol, action, quantity, price):
# 调用父类的基础检查
base_check = super().check_trade(symbol, action, quantity, price)
ifnotbase_check['allowed']:
returnbase_check
# 自定义风险检查
current_position = self.get_position(symbol)
portfolio_value = self.get_portfolio_value()
# 检查单日损失
ifself.daily_pnl<-self.max_daily_loss*portfolio_value:
return {
'allowed': False,
'reason': f'单日损失已达限额: {self.daily_pnl/portfolio_value:.2%}'
}
# 检查连续亏损
ifself.consecutive_losses>= self.max_consecutive_losses:
return {
'allowed': False,
'reason': f'连续亏损次数已达{self.consecutive_losses}次'
}
return {'allowed': True, 'reason': '通过所有风险检查'}
defupdate_pnl(self, pnl):
"""更新每日盈亏"""
self.daily_pnl += pnl
ifpnl<0:
self.consecutive_losses += 1
else:
self.consecutive_losses = 0
defreset_daily(self):
"""每日重置"""
self.daily_pnl = 0
# 使用增强风险管理
risk_manager = EnhancedRiskManager()
engine.add_risk_manager(risk_manager)
print("风险管理配置:")
print(f" 单股最大仓位: {risk_manager.max_position_size:.0%}")
print(f" 组合最大风险: {risk_manager.max_portfolio_risk:.0%}")
print(f" 止损比例: {risk_manager.stop_loss:.0%}")
print(f" 止盈比例: {risk_manager.take_profit:.0%}")
print(f" 单日最大损失: {risk_manager.max_daily_loss:.0%}")
print(f" 最大连续亏损: {risk_manager.max_consecutive_losses}次")通过上述代码示例,我们可以看到AKQuant确实具备:
如果你觉得这篇文章有用,欢迎点赞、转发、收藏、留言、推荐❤!
本文分享自 Nicholas与Pypi 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!