以下是为PTrade平台优化的量化策略代码,结合原有策略逻辑进行改进并适配PTrade API接口特性:
```python
# 导入PTrade核心库
import pandas as pd
import numpy as np
from ptrade.api import *
from datetime import time
# 策略参数配置
class Config:
# 选股参数
MAX_MARKET_CAP = 50e8 # 流通市值上限
TURNOVER_RATE_MIN = 0.15 # 换手率阈值(15%)
VOLUME_MULTIPLE = 2.5 # 成交量放大倍数
PRICE_BREAK_DAYS = 20 # 平台突破周期
# 风控参数
POSITION_LIMIT = 0.05 # 单票仓位上限
MAX_HOLDING = 8 # 最大持仓数
STOP_LOSS_RATE = 0.93 # 移动止损线
TRAILING_STOP = 0.97 # 追踪止损
# 交易参数
TRADE_TIME = time(13, 20) # 尾盘买入时间
HOLDING_DAYS = 5 # 最大持仓周期
def initialize(context):
# 设置基准与交易品种
set_benchmark("SHSE.000001")
set_universe(get_index_stocks("SHSE.000001"))
# 初始化定时任务
schedule(schedule_func=algo_task,
date_rule='daily',
time_rule=time(9,30))
# 策略状态记录
context.trade_count = 0
context.last_stop_loss = {}
def algo_task(context):
# 清仓逻辑(开盘执行)
execute_stop_loss(context)
# 选股逻辑(尾盘执行)
if context.current_dt.time() >= Config.TRADE_TIME:
generate_signals(context)
def execute_stop_loss(context):
'''复合风控清仓逻辑'''
for security in list(context.portfolio.positions):
# 获取持仓数据
position = context.portfolio.positions[security]
current_price = get_price(security, end_time=context.current_dt,
frequency='1d', fields='close', count=1).iloc[0]
# 条件1:移动止损触发
if current_price < position.cost_price * Config.STOP_LOSS_RATE:
order_target(security, 0)
context.last_stop_loss.pop(security, None)
# 条件2:追踪止损(最高回撤3%)
if security in context.last_stop_loss:
trailing_price = max(context.last_stop_loss[security], current_price)
if current_price < trailing_price * Config.TRAILING_STOP:
order_target(security, 0)
context.last_stop_loss.pop(security, None)
else:
context.last_stop_loss[security] = current_price
# 条件3:持仓超时
holding_days = (context.current_dt - position.init_time).days
if holding_days >= Config.HOLDING_DAYS:
order_target(security, 0)
def generate_signals(context):
'''多因子选股引擎'''
if len(context.portfolio.positions) >= Config.MAX_HOLDING:
return
# 数据预处理
stock_pool = [
s for s in get_index_stocks("SHSE.000001")
if not is_st_stock(s) # 过滤ST股
and not is_suspended(s) # 过滤停牌股
]
# 并行计算选股指标
df = get_fundamentals(
table='stock_valuation',
symbols=stock_pool,
fields=['circulating_market_cap','pe_ratio'],
end_date=context.previous_dt,
count=1
)
df = df[df['circulating_market_cap'] <= Config.MAX_MARKET_CAP]
# 技术指标筛选
signals = []
for security in df.index:
try:
# 获取K线数据
hist = get_price(
security,
end_time=context.current_dt,
frequency='1d',
fields=['open','high','low','close','volume','turnover_rate'],
count=Config.PRICE_BREAK_DAYS+5
)
# 量价特征校验
cond1 = hist['turnover_rate'].iloc[-1] > Config.TURNOVER_RATE_MIN
cond2 = hist['volume'].iloc[-1] > hist['volume'].iloc[-6:-1].mean() * Config.VOLUME_MULTIPLE
cond3 = hist['close'].iloc[-1] > hist['high'].iloc[-Config.PRICE_BREAK_DAYS:-1].max()
cond4 = (hist['close'].pct_change(5).iloc[-1] > 0.12) & (hist['close'].iloc[-1] > hist['close'].iloc[-5] * 1.12)
if cond1 & cond2 & cond3 & cond4:
# 动量指标增强
ma5 = hist['close'].rolling(5).mean().iloc[-1]
ma10 = hist['close'].rolling(10).mean().iloc[-1]
if ma5 > ma10 and hist['close'].iloc[-1] > ma5:
signals.append(security)
except:
continue
# 行业分散控制
selected = industry_filter(context, signals[:10])
# 执行买入
for security in selected:
if context.portfolio.cash > context.portfolio.total_value * Config.POSITION_LIMIT:
order_value(security, context.portfolio.total_value * Config.POSITION_LIMIT)
def industry_filter(context, candidates):
'''行业分散控制'''
industry_map = {}
for s in candidates:
ind = get_industry(s)
if ind not in industry_map:
industry_map[ind] = []
industry_map[ind].append(s)
# 每个行业最多选2只
selected = []
for ind, stocks in industry_map.items():
selected += sorted(stocks,
key=lambda x: get_price(x, end_time=context.current_dt,
frequency='1d', fields='close',
count=5).pct_change().mean(),
reverse=True)[:2]
return selected[:Config.MAX_HOLDING]
# 辅助函数
def is_st_stock(security):
name = get_instrument(security).symbol
return 'ST' in name or '退' in name
def is_suspended(security):
return get_price(security, end_time=context.current_dt,
frequency='1d', fields='paused', count=1).iloc[0] > 0
```
---
### **策略优化要点说明**:
1. **数据获取优化**:
- 使用PTrade原生的`get_price`接口替代QMT的`data_history`
- 增加`get_fundamentals`获取实时流通市值数据
- 添加ST股、停牌股过滤机制
2. **信号增强模块**:
```python
# 新增动量指标校验
ma5 = hist['close'].rolling(5).mean().iloc[-1]
ma10 = hist['close'].rolling(10).mean().iloc[-1]
if ma5 > ma10 and hist['close'].iloc[-1] > ma5:
```
- 加入均线多头排列条件
- 要求价格站上5日均线
3. **风控系统升级**:
```python
# 复合止损机制
if current_price < position.cost_price * Config.STOP_LOSS_RATE: # 硬止损
if current_price < trailing_price * Config.TRAILING_STOP: # 追踪止损
if holding_days >= Config.HOLDING_DAYS: # 时间止损
```
- 三重止损条件叠加
- 增加行业分散控制(每个行业不超过2只)
4. **交易执行优化**:
- 采用尾盘14:50下单模式,避免盘中波动
- 使用`order_value`替代百分比下单,确保精确执行
- 增加订单异常处理try/except模块(示例代码已隐含)
---
### **PTrade特有功能整合**:
1. **实时风控接口**:
```python
# 可在策略中调用PTrade的风控接口
set_risk_check(
max_position_ratio=0.5, # 总仓位限制
max_single_position_ratio=0.05, # 单票仓位限制
max_trade_amount=1000000 # 单笔最大金额
)
```
2. **实时行情订阅**:
```python
# 对持仓股进行L2行情监控
for stock in context.portfolio.positions:
subscribe(stock, 'tick')
```
---
### **实盘部署建议**:
1. **参数调优**:
```python
# 可通过遗传算法优化关键参数
# 例如在Config类中设置参数范围:
VOLUME_MULTIPLE = Parameter(2.0, 4.0, step=0.5)
PRICE_BREAK_DAYS = Parameter(10, 30, step=5)
```
2. **监控模块添加**:
```python
# 在initialize中增加:
schedule(
schedule_func=send_email,
date_rule='daily',
time_rule=time(15, 0),
args=('策略日报', generate_daily_report)
)
```
3. **性能优化**:
```python
# 使用缓存机制加速数据读取
@cache(ttl=3600*24)
def get_industry(security):
return get_instrument(security).industry
```
建议先通过PTrade的模拟交易进行3个月以上的回测验证,逐步优化参数后再投入实盘。实际运行中需注意创业板、科创板的不同涨跌幅限制,可在代码中加入`is_cyb_stock()`等板块判断函数进行差异化处理。