尽管bt框架内置了不少算子,但扩展自己的算子,才是我们掌握了这个框架的标志。这意味着我们真正可以驾驭这个框架,实现咱们想实现的功能。
实现算子并不复杂,但要设计出一个良好的可复用的算子,还是需要花点心思。
框架内置的SelectMomentum算子,按N天的收益率(动量)对标的进行从大到小排序,取前N个。这个算子在轮动策略中非常有效。
在这个不够灵活,我们希望可以传入任何信号(Siganl),都可以进行排序。
我们看下源代码里SelectMomentum的实现:
它继承了AlgoStack,然后初始化的时候,传入StatTotalReturn和SelectN两个算子,搞定。
这就是代码复用的力量。
class SelectHolding(bt.Algo):
def __init__(self):
pass
def __call__(self, target):
holding = []
if target.now in target.positions.index:
sig = target.positions.loc[target.now] > 0
se_pos = sig[sig == True].index # noqa: E712
universe = target.universe.loc[target.now, list(se_pos)].dropna()
holding = list(universe[universe > 0].index)
if 'selected' not in target.temp.keys():
return True # 如果前而有selected,则加上当前持仓。 selected = target.temp['selected'] selected = list(set(selected + holding)) target.temp['selected'] = selected return True
其中StatTotalReturn这个算子计算当前所有标的收益率,缓存在target.temp[‘stat’]中;SelectN读取这个stat中的值,对标的进行排序,取最大的前N个。
class SelectMomentum(AlgoStack): def __init__( self, n, lookback=pd.DateOffset(months=3), lag=pd.DateOffset(days=0), sort_descending=True, all_or_none=False, ): super(SelectMomentum, self).__init__( StatTotalReturn(lookback=lookback, lag=lag), SelectN(n=n, sort_descending=sort_descending, all_or_none=all_or_none), )
一个极简的,根据信号从大到小排序的算子实现如下:
Signal可以是信号的dataframe,也可以是变量字符串;K就是取前N个。
class SelectTopK(bt.AlgoStack):
def __init__(self, signal, K):
super(SelectTopK, self).__init__(bt.algos.SetStat(signal), bt.algos.SelectN(K))
代码同步在星球下,请大家自取:
吾日三省吾身
昨天的文章,几个反思点: 生产有长期价值的产品。
这个不确定的时代,你无法规划长远,但不意味着你无所作为。而是说计划赶不上变化,临渊羡鱼,不如退而结网,当下看到——有生产长期价值产品的机会,干就是了。——也许这就是局部最优,但没关系,没有人真的可以看到所谓的全局最优。——机器学习的搜索算法也是如此。
若你仍想思考更长期的未来。
不是你想过什么样的生活,这个太容易,太廉价,谁不想权倾天下,富可敌国?周游列国,结交名仕。
把“我想要”,换成“我能给”。
芒格说,“得到一件想要的东西最好的办法,就是想办法配得上它”。
你要想,什么样的能力和付出,配过这样的生活。
这个社会,本质就是价值交换,你想得到什么,取决你能拿什么东西来换。
80%的精力做当下最优,能产出阶段产品的事情。
20%的精力随兴趣漫游,尝试各种新事情,积极拥抱各种可能性。
历史文章:
发布者:股市刺客,转载请注明出处:https://www.95sca.cn/archives/103402
站内所有文章皆来自网络转载或读者投稿,请勿用于商业用途。如有侵权、不妥之处,请联系站长并出示版权证明以便删除。敬请谅解!