add: 新增聚宽社区文章爬取分析(姜维)
This commit is contained in:
@@ -0,0 +1,142 @@
|
||||
标题: 聚宽策略性能优化实战指南
|
||||
链接: 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倍速度提升
|
||||
|
||||
---
|
||||
|
||||
**总结**:策略性能优化的核心是"减少重复计算、利用向量化操作、合理分配计算时机"。通过这些优化,可以显著提升策略回测和实盘运行效率。
|
||||
Reference in New Issue
Block a user