今日策略:全球资产风险平价,年化8%,就图个省心(源代码+数据)

今日策略:目标波动率。

在风险平价的基础上,我们可以预设目标波动率,以此调节风险资产的比重。但又尽量保持在风险平价最优。

目标波动率是在风险平价的基础上,测算组合的目标波动率,如果波动率过高,则降低风险资产比例,反之提升风险资产比例。

我们把目标波动率设定在7%左右,这个大家可以算行测试:

图片

策略配置文件在代码发如下位置:

图片

class TargetVol(Algo):
    def __init__(
            self,
            target_volatility,
            lookback=pd.DateOffset(months=3),
            lag=pd.DateOffset(days=0),
            covar_method="standard",
            annualization_factor=252,
            exclude=[]
    ):
        super(TargetVol, self).__init__()
        self.target_volatility = target_volatility
        self.lookback = lookback
        self.lag = lag
        self.covar_method = covar_method
        self.annualization_factor = annualization_factor
        self.exclude = exclude

    def __call__(self, target):
        #current_weights = target.temp["weights"]
        #selected = current_weights.keys()

        # if there were no weights already set then skip
        #if len(selected) == 0:
        #    return True

        selected = target.temp["selected"]
        curr_symbols = target.df_bar.index

        selected = [s for s in selected if s in curr_symbols]

        t0 = target.now - self.lag
        prc = target.df_close.loc[t0 - self.lookback: t0, selected]

        returns = prc.pct_change().dropna()

        if len(returns) < 10:
            return True

        tw = calc_erc_weights(
            returns,
            initial_weights=None,
            risk_weights=None,
            covar_method="ledoit-wolf",
            risk_parity_method="ccd",
            maximum_iterations=100,
            tolerance=1e-8,
        )


        current_weights = tw.dropna().to_dict()
        target.temp['weights'] = current_weights

        # calc covariance matrix
        # if self.covar_method == "ledoit-wolf":
        #    covar = sklearn.covariance.ledoit_wolf(returns)
        if self.covar_method == "standard":
            covar = returns.cov()
        else:
            raise NotImplementedError("covar_method not implemented")

        weights = pd.Series(
            [current_weights[x] for x in covar.columns], index=covar.columns
        )

        vol = np.sqrt(
            np.matmul(weights.values.T, np.matmul(covar.values, weights.values))
            * self.annualization_factor
        )

        # 波动率偏小
        count = 0
        if vol < self.target_volatility:
            while vol < self.target_volatility:
                count += 1
                if count > 10:
                    break

                mul = self.target_volatility / vol

                for k in target.temp["weights"].keys():
                    if k in self.exclude:  # exclude通常为债券等低风险
                        continue
                    target.temp["weights"][k] = (
                            target.temp["weights"][k] * mul
                    )

                weights = pd.Series(
                    [target.temp["weights"][x] for x in covar.columns], index=covar.columns
                )

                vol = np.sqrt(
                    np.matmul(weights.values.T, np.matmul(covar.values, weights.values))
                    * self.annualization_factor
                )

            if vol is float('NaN'):
                return True
            weights = pd.Series(
                [target.temp["weights"][x] for x in covar.columns], index=covar.columns
            )
            # print(target.temp["weights"])
            target.temp["weights"] = weights / weights.sum()
            # print(target.temp["weights"])
            return True

        for k in target.temp["weights"].keys():
            if k in self.exclude:  # exclude通常为债券等低风险
                continue
            target.temp["weights"][k] = (
                    target.temp["weights"][k] * self.target_volatility / vol
            )

        '''

        print(self.target_volatility[k] / vol,weights, new_weights)
        print(new_vol)
        '''

        return True

目前积累的策略如下:

图片

当前已经积累的策略集:

图片

今天的策略是风险平价:

图片

name = "全球大类资产风险平价"
desc = "全球大类资产风险平价"
symbols = ["563300.SH", "510300.SH", "510500.SH", "512100.SH", "159915.SZ", "159967.SZ", "159920.SZ", "513100.SH", "513500.SH", "518880.SH", "159985.SZ", "513520.SH", "510050.SH"]
algo_period = "RunMonthly"
algo_period_days = 20 #RunPeriod时有效
rules_buy = []
at_least_buy = 1
rules_sell = []
at_least_sell = 1
order_by = ""
topK = 1
dropN = 0
b_ascending = 0
algo_weight = "WeightERC"
algo_weight_fix = []
feature_names = []
features = []
start_date = "20100101"
end_date = ""
commission = 0.0001
slippage = 0.0001
init_cash = 1000000
benchmark = "510300.SH"

算子代码如下:

class WeightERC(Algo):
    """
    Sets temp['weights'] based on equal risk contribution algorithm.

    Sets the target weights based on ffn's calc_erc_weights. This
    is an extension of the inverse volatility risk parity portfolio in
    which the correlation of asset returns is incorporated into the
    calculation of risk contribution of each asset.

    The resulting portfolio is similar to a minimum variance portfolio
    subject to a diversification constraint on the weights of its components
    and its volatility is located between those of the minimum variance and
    equally-weighted portfolios (Maillard 2008).

    See:
        https://en.wikipedia.org/wiki/Risk_parity

    Args:
        * lookback (DateOffset): lookback period for estimating covariance
        * initial_weights (list): Starting asset weights [default inverse vol].
        * risk_weights (list): Risk target weights [default equal weight].
        * covar_method (str): method used to estimate the covariance. See ffn's
          calc_erc_weights for more details. (default ledoit-wolf).
        * risk_parity_method (str): Risk parity estimation method. see ffn's
          calc_erc_weights for more details. (default ccd).
        * maximum_iterations (int): Maximum iterations in iterative solutions
          (default 100).
        * tolerance (float): Tolerance level in iterative solutions (default 1E-8).


    Sets:
        * weights

    Requires:
        * selected

    """

    def __init__(
            self,
            lookback=pd.DateOffset(months=3),
            initial_weights=None,
            risk_weights=None,
            covar_method="ledoit-wolf",
            risk_parity_method="ccd",
            maximum_iterations=100,
            tolerance=1e-8,
            lag=pd.DateOffset(days=0),
    ):
        super(WeightERC, self).__init__()
        self.lookback = lookback
        self.initial_weights = initial_weights
        self.risk_weights = risk_weights
        self.covar_method = covar_method
        self.risk_parity_method = risk_parity_method
        self.maximum_iterations = maximum_iterations
        self.tolerance = tolerance
        self.lag = lag

    def __call__(self, target):
        selected = target.temp["selected"]
        curr_symbols = target.df_bar.index

        selected = [s for s in selected if s in curr_symbols]

        if len(selected) == 0:
            target.temp["weights"] = {}
            return True

        if len(selected) == 1:
            target.temp["weights"] = {selected[0]: 1.0}
            return True

        t0 = target.now - self.lag
        prc = target.df_close.loc[t0 - self.lookback: t0, selected]

        returns = prc.pct_change().dropna()
        if len(returns) < 10:
            return False
        # ERC = EqualRiskContribution(returns.cov())
        # ERC.solve()

        # tw = ERC.x
        # print(tw)

        tw = calc_erc_weights(
            returns,
            initial_weights=self.initial_weights,
            risk_weights=self.risk_weights,
            covar_method=self.covar_method,
            risk_parity_method=self.risk_parity_method,
            maximum_iterations=self.maximum_iterations,
            tolerance=self.tolerance,
        )

        target.temp["weights"] = tw.dropna().to_dict()
        return True

吾日三省吾身

想给一些量化新手提供更易用的“开箱即用”的平台。这几天调研了前端的开发。

有考虑过uni-app,ionic和flutter。

uni-app与ionic类似,都是web的解决方案,当然可以打包成app,flutter可以打包成原生的app。——当然app并非咱们直接的刚需,但有当然更好了。

三者缺点是都要引入新的技术栈。uni-app与ionic都支持vue3,而flutter背后是dart。

原先对于dart这种高级语言的形态还是很满意了。折腾了Andriod Studio,androd sdk, flutter sdk等,包非常大,动辄几个G,加上在外网就更慢了。在启动安卓虚拟机时,最终决定放弃了。——还是太重。

想起之前折腾过几天的flet。

又过了这么一段时间,有惊喜。

之前体验过flet 和 nicegui。工欲善其事,必先利其器-NiceGUI:AI量化投资研究开发,后来用nicegui是直接原因是当前flet竟然没有Datetime Picker控件。之后又不用nicegui的原因是,它的控件更面像桌面程序。做出来的web感觉四不像。而我们真正的诉求的手机H5为主,App为辅

Flet开发的图,还行吧。

图片

 

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

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

相关推荐

发表回复

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