年化41.4%的指数多因子轮动与年化26.5%大类资产动量轮动,准备实盘跟踪。(代码下载)

吾日三省吾身。

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

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

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

我们在做一件什么事呢?——低门槛快速实验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

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

日拱一卒,功不唐捐。

我们的目标是星辰大海,围绕投资理财的话题,是一辈子的事情,不着急。

昨天群里星球的同学分享了一个策略——10年12倍,我看了一下,使用我们的框架应该几行代码就可以搞定。

这是一个围绕大类资产轮动的简单策略。使用黄金、美股、A股进行动量轮动。黄金、纳指、创业板和沪深300代表了不同类型、风格和市场的资产,它们之间具有一定的互补性。

我们先设定一个基准: 大类资产的风险平价,季度再平衡:

年化11.1%,最大回撤17.6%。收益率与标普500差不多,但回撤小得多,这就是投资组合,风险平价的价值所有。

图片

from engine.env import Env
from engine.algo.algo_weights import *
from engine.algo.algos import *

etfs = [
    '510300.SH',  # 沪深300ETF
    '159915.SZ',  # 创业板
    '518880.SH',  # 黄金ETF
    '513100.SH',  # 纳指ETF
]

from engine.datafeed.dataloader import Hdf5Dataloader

loader = Hdf5Dataloader(etfs, start_date="20100101")
df = loader.load()
bench_loader = Hdf5Dataloader(['000300.SH', 'SPX'], start_date='20100101')

e = Env(df, benchmarks=bench_loader.load())
e.set_algos([
    RunQuarterly(),
    SelectAll(),
    WeightRP()
])
e.backtest_loop()
e.show_results()

然后我们上今天的策略——动量轮动:

年化26.7%,最大回撤24.9%,是个不错的策略!

图片

图片

代码在如下位置,已经在星球更新:知识星球与开源项目:万物之中,希望至美

图片

from engine.datafeed.dataloader import Hdf5Dataloader
from engine.env import Env
from engine.algo import *

start_date = '20100101'

etfs = [
        '510300.SH',  # 沪深300ETF
        '159915.SZ',  # 创业板
        '518880.SH',  # 黄金ETF
        '513100.SH',  # 纳指ETF
    ]

loader = Hdf5Dataloader(etfs, start_date=start_date)

fields = ['roc(close,20)', 'std(volume,20)', 'bias(close,20)',
          'roc(close,5)', 'std(volume,5)', 'bias(close,5)',
          'rank(roc_20)']
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','SPX'], start_date=start_date)

e = Env(name='roc_20_index', df=df, benchmarks=bench_loader.load())
e.set_algos([
    RunDays(2),
    # SelectAll(),
    #SelectBySignal(buy_rules=[], sell_rules=['ind(roc_20)<-0']),
    SelectTopK(drop_top_n=0, K=1, order_by='rank'),
    WeightEqually()
])

e.backtest_loop()
e.show_results()

实践再一次证明,择时从来并不容易,而找到合适的标的池子,进行轮动是可行的。

我们现在有两个策略,今天这个虽然简单,我打算实盘了,就是挑选动量最强的标的持有,简单操作性强。另外是昨天的:

年化27.7%,夏普大于1:加上RSRS大盘择时的行业指数多因子轮动(代码下载)

从29个行业指数ETF取强势的1支轮动。

年化收益41.4%。

图片

图片

图片

以上两个策略进行实盘跟进。

为了方便每日选股操作,我会在GUI系统里提供这样的功能,方便看数据和实盘操作。

近期策略:

年化24.9%:基于动量、波动率、乖离率的多因子合成策略的指数轮动。(代码+数据下载)

行业指数轮动:一个可实盘策略的“魔改”历程,十年年化15%(策略+代码+数据下载)

发布者:股市刺客,转载请注明出处:https://www.95sca.cn/archives/104062
站内所有文章皆来自网络转载或读者投稿,请勿用于商业用途。如有侵权、不妥之处,请联系站长并出示版权证明以便删除。敬请谅解!

(0)
股市刺客的头像股市刺客
上一篇 2024 年 7 月 29 日
下一篇 2024 年 7 月 29 日

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注