年化收益19.3%, 最大回撤率:-18.32​%。

按quantlab5.x的规划,我们同样纳入backtrader,但不做太多的封装。

使用notebook来呈现它的策略开发过程。

首先同样是数据预处理和加载:

backtrader与bt、pybroker不同:

它是加载一个个独立的dataframe,然后需要加一个字段——openinterest,这是期货里的概念,暂时用不到,直接置为0即可。

@staticmethod
def get_backtrader_df(symbol: str):
df = CSVDataloader.get_df([symbol])
df.set_index('date', inplace=True)
df['openinterest'] = 0
df = df[['open', 'high', 'low', 'close', 'volume', 'openinterest']]
return df

同样实现昨天的策略:

class roc_trend(bt.Strategy):
# 参数定义
params = dict(
period=20, # 动量周期
)

def __init__(self):
self.roc = bt.indicators.ROC(self.data, period=self.p.period)
# self.roc = bt.talib.ROC(self.data, period=self.p.period)

def next(self):
if not self.position: # not in the market
if self.roc[-1] > 0.08: # if fast crosses slow to the upside
self.order_target_percent(self.data, 0.99) # enter long
# self.buy() # enter long elif self.roc[-1] < 0: # in the market & cross to the downside self.close() # close long position

客观讲,backtreader更接近传统像zipline和quantopian的逻辑:

支持order_target_percent(目标比例仓位)这样的api。

我们使用quantstats做结果分析:

图片

代码在如下位置:

图片

对比一下:

图片

吾日三省吾身

 

人们习惯低估做成一件事情的难度,尤其在开发回测系统这件事上。

要做一个demo几行代码就够了,比如一个向量化的信号回测策略。

但,要写一个完善的,稳定的系统,那需要考虑的事情,细节就相当多了。

一开始,低估难度,追求可控性,选择自己从零开始写。

刚开始当然很爽,很有成就感。

但越后面,发现稳定性,扩展性,功能。

不如选择成熟的框架,即便一开始有学习成本,甚至有些看似不合理的地方。

 

第二个问题,在选择框架方面,同样过于追求可控性,代码可读性。忽视了,其实,稳定性,生态,扩张性才是最重要的。真正需要改造框架的机会不多!

 

第三个问题,在界面上,网站上,数据自动更新,缓存上,规则配置上花了不少时间,没有直奔主题。真正的点是策略,可实盘交易的策略,交易体系。

——大道至简!福尔摩斯只关心且精通与侦破有关的知识,对于地球围绕太阳转还是反过来,他完全不关心,甚至觉得,你就算知道了,也应该尽快忘掉它!。

精力有限,专注于最重要的事情上并取得突破。

 

在量化投资配置,还是“与交易为生”的投资能力上摇摆。——这是基础逻辑。

 

“具备职业投资的能力,但不需要依赖它谋生”——以出世的心态做入世的事情。

 

感悟

阅读三体有一个体会,当你在一段关系中,由于某种原因暂时无法离开,如同三体人在黑暗森林威慑下,应该报持何种态度对待地球人?

1、真心诚意地满足对方。

2、时刻准备让自己离的开它。

一段感情如是,职场纷争亦然。

 

几个心态:

“允许一切发生”的淡定与释然。

“凡事发生必有利于我”——生命中看似让你不爽,不愉快的人和事,必定是来“提醒你”,还有进步与提升的空间,或者,在某些方面需要最出改变。

“避免与猪在泥地里摔跤”。

你要做的是,有能力离开泥地。

社会运行规律是价值交换,让自己强大。

然后笑看风云。

你会发现身边的人都会越来越美好。

基于pybroker实现的“创业板-择时策略”,策略代码在这个notebook里,

图片

首先加载数据——这里可以加载多个symbols,

from datafeed.dataloader import CSVDataloader
df = CSVDataloader.get_df(['000300.SH', #沪深300
'000905.SH', #创业板
'159915.SZ'
])
df

得到如下数据:

图片

自定义一个指标,这里我们没有使用pandas的函数,而是使用numba来加速。

这里需要说明的是ctx里的数据,已经是按symbol,group_by之后的结果,因此可以直接使用。

import talib
import pybroker
import numpy as np
from numba import njit

def roc_N(bar_data, lookback):

    @njit  # Enable Numba JIT.
    def vec_roc(values):
        # Initialize the result array.
        n = len(values)
        out = np.array([np.nan for _ in range(n)])

        for i in range(lookback, n):
            out[i] = values[i]/values[i-lookback] -1
        return out

    # Calculate with close prices.
    return vec_roc(bar_data.close)

这里的指标,还有更简洁的实现方式,调用talib:

roc_20 = pybroker.indicator('roc_20', lambda data: talib.ROC(data.close, timeperiod=20)/100)

与如下这行代码是等价的:

roc_20 = pybroker.indicator('roc_20', roc_N, lookback=20)

定义好的指标,就可以开始写策略了:

def pick_time(ctx):
    if ctx.indicator("roc_20")[-1] > 0.08:
        ctx.buy_shares = ctx.calc_target_shares(1.0)
    if ctx.indicator("roc_20")[-1] < 0:

ctx.sell_all_shares()

 

roc_20 = pybroker.indicator('roc_20', roc_N, lookback=20)

from pybroker import Strategy
strategy = Strategy(df, '20100101','20240601')
strategy.add_execution(pick_time, ['159915.SZ'],indicators=[roc_20])
result = strategy.backtest()
result.orders

图片

图片

年化收益19.3%, 最大回撤率:-18.32%。

这里需要说明的是,简单的信号择时策略,bt框架也是胜任的,而且代码量会更少。

不过如果要涉及更复杂的操作,比如加减仓策略,止损、止赢等,那bt就不太方便了,或者多重逻辑判断,多重if-else信号,bt也比较麻烦。

因此,还是那句话,每个框架有其优缺点。

比如backtesing.py就支持多个参数网格调优,搜寻最优参数——类似backtrader的单symbol版本,但代码更简洁,它不支持多symbols。

backtrader不支持机器学习,qlib不支持传统规则量化。

vnpy和wonder trader偏重实盘,写策略就有点麻烦了。

所以,都可以关注一下,艺多不压身,当然更重要的是,策略、思路、因子。——框架只是工具罢了。

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

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

相关推荐

发表回复

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