前文数据表明,右侧追击确实是抓取券商强势行情的一把利器。不过策略也有一个明显的弊端,也是有待优化的地方——追击成功率。从整个券商行业来看,10次追击,都未必有一次成功。在实战中,每一次失败,不仅意味着对资金的无效占用,更是真金白银的流失。
所以,让策略识别假突破,提高追击成功率尤为重要。一般来看,强势突破会伴随着成交量的释放,本文的策略优化将围绕成交量展开。成交量是识别是否为假突破的重要参考指标,通过它,能将一部分假突破挡在门外,减少摩擦成本。
另外,策略中追击成功的机会是十分稀有且宝贵的,整体收益也全都仰仗于它们。一次成功的收益可以覆盖十几次乃至几十次的失败亏损,所以策略调优必须遵循一个原则:在不错失任何一次追击成功机会的前提下,尽可能减少追击次数!
1.原始追击情况
在加入成交量因子后,判断策略是否优化最首要的指标就是成功次数和追击成功率。先获取策略未加入放量判断时的追击情况,作为对照。
import akshare as ak
import pandas as pd
import quan_trade
import time
# 从本地读取所有券商股票代码
dealer_df = pd.read_csv('dealer_data/symbols.csv',dtype = {'symbol':str})
symbols.csv为爬虫获取到的49支券商股票代码,该文件放在了https://github.com/kaiforone/quantized-trade/tree/main/dealer_data
# 根据订单记录计算追击详情及汇总的函数
def get_profit(order,symbol,begin_date,capital = 100000):
# 创建profit_df用来存放每次追击的情况, summary_df存放每只股票的追击汇总
profit_df = pd.DataFrame(
columns = ['symbol','start_time','end_time', 'capital', 'attack_times', 'profit', 'profit_rate','total_profit_rate'])
summary_df = pd.DataFrame(columns = [
'跟踪起始时间','代码','公司','本金','总追击次数','成功次数','追击成功率','单次最大亏损','单次最大盈利','总利润','资金占用时间/天','折合年化'
])
# 订单记录为空,直接返回
if order.empty:
print(symbol, ": 订单记录为空")
return profit_df,summary_df
# 初始化部分数据
start_time = None
attack_times = 0
profit = 0
amount = 0 # 记录每次追击累积交易的数量
# 遍历订单记录,计算每次追击后的数据,存放到profit_df
for i in range(0,order.shape[0]):
if order.iloc[i]['trade_type'] == 'B':
# 记录每次追击开始的时间
if attack_times == 0:
start_time = order['date'].iloc[i]
#计算累计追击次数以及累计买入数量
attack_times += 1
amount += capital / 5 / order.iloc[i]['trade_price']
else :
# 数据存放
profit_df = profit_df.append({
'symbol':symbol,
'start_time':start_time,
'end_time':order['date'].iloc[i],
'capital':capital,
'attack_times':attack_times,
'profit': order.iloc[i]['trade_price'] * amount - capital / 5 * attack_times,
'profit_rate': (order.iloc[i]['trade_price'] * amount /(capital / 5 * attack_times) - 1) * 100,
'total_profit_rate':(order.iloc[i]['trade_price'] * amount - capital / 5 * attack_times) / capital * 100
},ignore_index=True)
# 卖出意味着本次追击结束,清零
attack_times = amount = 0
### 追击详情汇总
summary_df = pd.DataFrame({
'跟踪起始时间':begin_date,
'代码':symbol,
'公司': dealer_df[dealer_df['symbol'] == symbol].company,
'本金': capital,
'总追击次数' : profit_df['attack_times'].count(),
'成功次数': profit_df[profit_df['attack_times'] == 5].attack_times.count(),
'追击成功率':profit_df[profit_df['attack_times'] == 5].attack_times.count() / profit_df['attack_times'].count() * 100,
'单次最大亏损':profit_df['profit'].min(),
'单次最大盈利':profit_df['profit'].max(),
'总利润':profit_df['profit'].sum(),
'资金占用时间/天':(profit_df['end_time'] - profit_df['start_time']).dt.days.sum() + profit_df.start_time.count(),
'折合年化':((profit_df['profit'].sum() /capital + 1) ** (365 / ((profit_df['end_time'] - profit_df['start_time']).dt.days.sum() + profit_df.start_time.count())) -1) * 100
})
return profit_df, summary_df
东方财富的追击情况
单只股票方便观察真假突破时的成交量特性,对策略进行预调优,然后拿整个行业来验证
df = ak.stock_zh_a_hist(symbol='300059', period="daily", start_date="20120101", end_date='20221231', adjust="qfq")
trade = quan_trade.Trade('300059', df, 'right_attack', 100 , 1000000, max_volatility = 10)
trade.main()
profit_df, su