Files
sanguo_quant_live/platform/research/joinquant_articles/article_02.txt
T

143 lines
3.9 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
标题: 聚宽策略性能优化实战指南
链接: https://www.joinquant.com/view/community/detail/2
分类: 回测
================================================================================
# 聚宽策略性能优化实战指南
## 一、代码结构优化
### 1.1 合理分配计算逻辑
**避免在handle_data中进行耗时计算**
```python
# 不推荐的写法
def handle_data(context, data):
# 在handle_data中进行复杂计算
for stock in g.stock_pool:
# 计算技术指标
prices = history(60, '1d', 'close', [stock])
ma20 = prices.mean()
ma60 = prices.mean()
std = prices.std()
# ... 更多计算
# 交易决策
if condition:
order(stock, amount)
# 推荐的写法
def before_trading_start(context, data):
# 在开盘前完成所有复杂计算
g.signals = {}
prices = history(60, '1d', 'close', g.stock_pool)
for stock in g.stock_pool:
ma20 = prices[stock][-20:].mean()
ma60 = prices[stock].mean()
std = prices[stock].std()
g.signals[stock] = {'ma20': ma20, 'ma60': ma60, 'std': std}
def handle_data(context, data):
# handle_data中只进行简单的交易决策
for stock in g.stock_pool:
signal = g.signals[stock]
if signal['ma20'] > signal['ma60']:
order_target_percent(stock, 0.01)
```
### 1.2 使用全局变量缓存
```python
def initialize(context):
g.stock_pool = get_index_stocks('000300.XSHG')
# 初始化缓存字典
g.cache = {}
def before_trading_start(context, data):
# 只在数据变化时更新缓存
current_date = context.current_date.strftime('%Y-%m-%d')
if current_date not in g.cache:
g.cache[current_date] = {
'prices': get_price(g.stock_pool, count=60, end_date=context.previous_date),
'factors': calculate_factors(g.stock_pool, context.previous_date)
}
```
## 二、向量化操作替代循环
### 2.1 利用Pandas向量化
```python
# 低效:Python循环
def calculate_returns_loop(prices):
returns = {}
for stock in prices.columns:
returns[stock] = prices[stock].pct_change()
return returns
# 高效:Pandas向量化
def calculate_returns_vectorized(prices):
return prices.pct_change()
```
### 2.2 使用TA-Lib
```python
import talib
# 不推荐:自己实现指标
def my_ma(prices, window):
ma = []
for i in range(len(prices)):
if i < window - 1:
ma.append(None)
else:
ma.append(sum(prices[i-window+1:i+1])/window)
return ma
# 推荐:使用TA-Lib
def talib_ma(prices, window):
return talib.SMA(prices, timeperiod=window)
```
## 三、减少不必要的输出
### 3.1 策略逻辑与数据记录分离
```python
# 不推荐:每个bar都记录大量数据
def handle_data(context, data):
for stock in g.stock_pool:
record(**{f'{stock}_price': data[stock].close})
record(**{f'{stock}_position': context.portfolio.positions[stock].amount})
# 推荐:只在关键时间点记录,使用批量记录
def after_trading_end(context, data):
# 每天结束时记录一次关键指标
record(
portfolio_value=context.portfolio.total_value,
cash=context.portfolio.cash,
leverage=context.account.leverage
)
```
## 四、实践案例
**优化前**
- 策略回测时间:30分钟
- 问题:在handle_data中计算所有技术指标,使用Python循环
**优化后**
- 策略回测时间:5分钟
- 改进措施:
1. 将技术指标计算移到before_trading_start
2. 使用TA-Lib替代自行实现的指标
3. 利用Pandas向量化操作
4. 减少记录频率,只在每天结束时记录
**性能提升**6倍速度提升
---
**总结**:策略性能优化的核心是"减少重复计算、利用向量化操作、合理分配计算时机"。通过这些优化,可以显著提升策略回测和实盘运行效率。