打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
沪深300成份股的量化多因子:年化20.3%

原创文章第273篇,专注“个人成长与财富自由、世界运作的逻辑与投资"。

吾日三省吾身。

以自己喜欢的方式过这一生。

昨天我突然想到这句:“以悦人之心,做悦己的事情”

你做的事情,要对别人有价值,对更多人有价值,对市场有价值,那么市场会给你回报。这叫“取悦他人”的目标,”悦己“,做你自己认同且喜欢,且擅长的事情。

我们在做一件什么事呢?——低门槛快速实验AI量化策略。

我们知道,因子也好,策略也罢,没有永远有效的圣杯。需要不停地观察市场,不断学习,迭代,这时候,需要一个好用的,低成本的策略研发平台。所以我们做“积木式”,“可视化”的策略开发过程。

前面的文章我们主要是围绕ETF、指数多因子轮动,大类资产配置展开。

今天开始我们正式进行A股股票市场。

记住我们的步骤:数据,因子,策略或模型,回测,分析,迭代

所以,第一步先搞定数据:从tushare直接下载hs300成份股,我们从沪深300开始。你会说这个成份股是一直在变的,没错,但我们只是用它作为一个基准池子,没有特别的影响。一直来就搞4000-5000支股票,数据量大,没必要。

有了300支的清单,我们需要下载历史复权数据

脚本在这里,把300支股票历史上全量的“后复权”数据保存到本地h5中。

文件400多M了,可能通过git很难下载了。

import akshare as ak
import pandas as pd
from engine.config import DATA_DIR, DATA_H5

df_codes = pd.read_csv(DATA_DIR.joinpath('hs300.csv').resolve())
codes = df_codes['con_code']

with pd.HDFStore(DATA_H5.resolve()) as s:
for i, code in enumerate(codes):
symbol = code
code = code[:6]
print(i, code)

df = ak.stock_zh_a_hist(symbol=code, period="daily", adjust="hfq")
df['symbol'] = symbol
df.rename(columns={'日期': 'date', '开盘': 'open', '收盘': 'close', '最高': 'high', '最低': 'low', '成交量': 'volume',
'换手率': 'turnover'}, inplace=True)
df['date'] = pd.to_datetime(df['date'])
df.set_index('date', inplace=True)
df = df[['symbol', 'open', 'high', 'low', 'close', 'volume', 'turnover']]

print(df)
s[symbol] = df

拿 指数的多因子试试:

from engine.datafeed.dataloader import Hdf5Dataloader
from engine.env import Env
from engine.algo import *
from engine.config import DATA_H5, DATA_DIR

df_codes = pd.read_csv(DATA_DIR.joinpath('hs300.csv').resolve())
codes = df_codes['con_code']


loader = Hdf5Dataloader(codes, start_date="20100101")
fields = ['roc(close,20)', 'std(volume,20)', 'bias(close,20)',
'roc(close,5)', 'std(volume,5)', 'bias(close,5)',
'rank(roc_20)+rank(bias_20)+rank(roc_5)+rank(bias_5)-rank(std_20)-rank(std_5)']
names = ['roc_20', 'std_20', 'bias_20',
'roc_5', 'std_5', 'bias_5',
'rank']
df = loader.load(fields=fields, names=names)
bench_loader = Hdf5Dataloader(['000300.SH'])

e = Env(df=df, benchmarks=bench_loader.load(fields=['slope_pair(high,low,18)', 'zscore(rsrs_18,600)<-0.7'],
names=['rsrs_18', 'zscore']))
e.set_algos([
RunDays(days=10),
#RunWeekly(),
# SelectAll(),
#SelectBySignal(buy_rules=[], sell_rules=['ind(roc_20)<-0.08']),
SelectTopK(drop_top_n=1, K=10, order_by='rank', b_ascending=False),
PickTime(benchmark='000300.SH', signal='zscore'),
WeightEqually()
])

e.backtest_loop()
e.show_results()
#e.save_results()

优化了一下performance计算:

之前我们使用empyrical库来计算,我们可以自己计算,后续我们需要补充多个指标,大家最好熟悉指标的计算公式,当然二者计算是结果是一样的。

import pandas as pd
from datetime import datetime


class PerformanceUtils(object):

def rate2equity(self, df_rates):
df = df_rates.copy(deep=True)
df.dropna(inplace=True)
for col in df.columns:
df[col] = (df[col] + 1).cumprod()
return df

def equity2rate(self, df_equity):
df = df_equity.copy(deep=True)
df = df.pct_change()
return df

def calc_equity(self, df_equity):
df_rates = self.equity2rate(df_equity)
return self.calc_rates(df_rates)

def calc_rates(self, df_rates):
df_equity = self.rate2equity(df_rates)
df_rates.dropna(inplace=True)
df_equity.dropna(inplace=True)
# 累计收益率,年化收益
count = len(df_rates)
accu_return = round(df_equity.iloc[-1] - 1, 3)
annu_ret = round((accu_return + 1) ** (252 / count) - 1, 3)
# 标准差
std = round(df_rates.std() * (252 ** 0.5), 3)
# 夏普比
sharpe = round(annu_ret / std, 3)
# 最大回撤
mdd = round((df_equity / df_equity.expanding(min_periods=1).max()).min() - 1, 3)

ret_2_mdd = round(annu_ret / abs(mdd), 3)

ratios = [accu_return, annu_ret, std, sharpe, mdd, ret_2_mdd]

# df_ratio存放这里计算结果
df_ratios = pd.concat(ratios, axis=1)
# df_ratios.index = list(df_rates.columns)
df_ratios.columns = ['累计收益', '年化收益', '波动率', '夏普比', '最大回撤', '卡玛比率']

# 相关系数矩阵
df_corr = round(df_equity.corr(), 2)

start_dt = df_rates.index[0]
end_dt = df_rates.index[-1]
if isinstance(start_dt, str):
start_year = int(start_dt[:4])
end_year = int(end_dt[:4])
df_equity['trade_date'] = df_equity.index
df_equity.index = df_equity['trade_date'].apply(lambda x: datetime.strptime(x, '%Y%m%d'))
del df_equity['trade_date']
else:
start_year = start_dt.year
end_year = end_dt.year

'''

years = []
for year in range(start_year, end_year + 1):
sub_df = df_equity[str(year)]
if len(sub_df) <= 3:
continue
year_se = round(sub_df.iloc[-1] / sub_df.iloc[0] - 1, 3)
year_se.name = str(year)
years.append(year_se)
if len(years):
df_years = pd.concat(years, axis=1)
else:
df_years = None
'''
return df_ratios, df_corr# df_years
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
pandas向量化回测策略开发
一个简单好用的北上资金择时模型
如何使用机器学习检测欺诈?
100%高频使用代码集锦!
「手把手教你」Python计算股票收益率、Alpha和Beta值
Python学习教程:手把手教你搭建自己的量化分析数据库
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服