(28-5-02)使用隐马尔可夫模型交易比特币:实现交易策略(2)

2.6.3  使用模拟数据进行训练

在本项目中,原计划使用强化学习来优化我的交易策略,以提高在从HMM采样的模拟数据上的表现。然而鉴目前的模型,我认为这可能效果不佳。原因在于,HMM生成的样本与HMM训练时使用的价格数据并不相似。特别是,HMM在隐藏状态之间切换得太快,使得其整体行为比实际比特币数据更一致。接下来将尝试选择买入/卖出阈值,以在从HMM采样的模拟数据上优化策略的表现,然后在实际测试期间对该策略进行评估。结果表明,该策略在中等较高的摩擦率下通常不会采取任何操作,因此其效果远不如在真实数据上优化阈值所得到的策略。

(1)下面代码用于生成模拟的价格数据,基于HMM模型的参数和状态转移概率来模拟5000天的回报率,并将这些回报率转化为价格数据。最终,代码将生成的模拟价格数据绘制为对数尺度图,以便于观察模拟数据的趋势和波动。

s=0  # 初始状态
r=0  # 初始回报率
n=5000  # 模拟的天数
Rsampled=np.zeros(n)  # 用于存储生成的回报率数据

for t in range(n):
    # 根据HMM的转移概率选择下一个状态
    s=np.random.choice(range(3), p=hmm.TP[:, s])
    # 根据当前状态生成回报率,并加入噪声
    r=hmm.beta*r + hmm.MU[s] + np.random.randn() * hmm.sig
    Rsampled[t] = r

# 将回报率转化为价格数据
Psampled=np.exp(np.cumsum(Rsampled))
plt.semilogy(Psampled)
plt.ylabel('从HMM采样的模拟价格数据')
plt.xlabel('天数')
plt.show()

上述代码的实现流程如下:

  1. 初始化变量:设置初始状态和回报率变量。
  2. 模拟数据生成:利用HMM的转移概率和参数,生成5000天的模拟价格数据。
  • 状态转移:根据HMM的状态转移概率从当前状态选择下一个状态。
  • 价格回报率生成:根据当前状态生成回报率,并加入噪声。
  • 累积价格:将生成的回报率累积并计算价格数据。
  1. 绘图:绘制模拟价格数据的对数图,以展示生成的数据随时间的变化,如图2-12所示。

图2-12  模拟价格数据的对数图

(2)下面代码旨在使用模拟的价格数据(Psampled)来优化买入和卖出的策略。首先,代码通过back_train_pol函数计算不同摩擦率下的回报率和交易次数。接着,它通过对不同摩擦率下的策略进行回测,找到最佳的买入和卖出阈值,并绘制这些阈值以及对应的优化策略回报。最后,将优化策略的回报与简单的比特币投资的回报进行比较,展示摩擦率对策略性能的影响。

R, T = back_train_pol(hmm, Psampled)
Back_train_Return = np.zeros(100)
Buy_Price = np.zeros(100)
Sell_Price = np.zeros(100)

for i in range(100):
    f = friction[i]
    FR = np.log(R) + T * np.log(1 - f)
    ix = np.argmax(FR)
    i1 = np.mod(ix, res)
    i0 = int((ix - i1) / res)
    Back_train_Return[i] = np.exp(FR[i0, i1])
    Buy_Price[i] = X[i0]
    Sell_Price[i] = X[i1]

plt.plot(friction, Buy_Price, label='Buy threshold')
plt.plot(friction, Sell_Price, label='Sell threshold')
plt.xlabel('Friction rate')
plt.ylabel('Expected abnormal rate')
plt.legend()
plt.show()

plt.plot(friction, Back_train_Return, label='Optimized buy/sell policy')
plt.plot([0, np.max(friction)], [Psampled[-1] / Psampled[0], Psampled[-1] / Psampled[0]], label='Bitcoin investment')
plt.ylim([0, 1.1 * np.max(Back_train_Return)])
plt.xlabel('Friction rate')
plt.ylabel('Back testing return')
plt.legend()
plt.show()

执行上述代码后会绘制两个可视化图表,展示不同摩擦率下的优化策略性能:

  1. 买入/卖出阈值图:如图2-13所示,显示不同摩擦率下的买入和卖出阈值(Buy_Price 和 Sell_Price),横坐标为摩擦率,纵坐标为预期异常收益率。这张图帮助你理解在不同摩擦率下,优化策略选择的买入和卖出点。
  2. 优化策略回报图:如图2-14所示,显示不同摩擦率下的优化买入/卖出策略的回报(Back_train_Return),并将其与简单比特币投资的回报进行比较。图中会显示:优化策略的回报随摩擦率的变化、作为基准的比特币投资的回报(常数线,表示在没有进行优化策略下的投资回报)。

图2-13  买入/卖出阈值图

图2-14  优化策略回报图

这些图表将帮助我们评估不同摩擦率下优化策略的表现,并与传统比特币投资策略进行对比,从而更好地理解摩擦率对策略性能的影响。

(3)定义回测函数 back_test_pol,用于测试不同的买入和卖出策略在给定价格数据上的表现。函数 back_test_pol 输入了一个模型 mdl、摩擦率数组 friction、买入和卖出阈值 Buy_Price 和 Sell_Price 以及价格数据 Prices。它输出了不同策略下的投资组合状态 Portfolios 和价值 Value。投资组合状态记录了每个策略在每一天的现金和比特币持有量,价值则表示这些持有量的总价值。通过这个函数,用户可以评估不同策略在测试数据上的表现。

# 回测函数
def back_test_pol(mdl, friction, Buy_Price, Sell_Price, Prices):
    P = mdl.get_hidden_state_probabilities(Prices)  # 获取每个隐藏状态的概率
    EAR = mdl.get_expected_abnormal_rates(Prices)  # 获取预期异常收益率
    n = P.shape[0]  # 数据点数量
    Portfolios = np.zeros((100, n, 2))  # 初始化投资组合状态数组
    Value = np.zeros((100, n))  # 初始化投资组合价值数组
    
    for i in range(100):
        buy = Buy_Price[i]  # 当前策略的买入阈值
        sell = Sell_Price[i]  # 当前策略的卖出阈值
        rate = 1 - friction[i]  # 计算有效资金比例
        Portfolios[i, 0, 0] = 1  # 初始时全现金
        a = 'c'  # 初始状态为现金
        
        for t in range(n-1):
            if a == 'c' and EAR[t] > buy:
                Portfolios[i, t, 1] = rate * Portfolios[i, t, 0] / Prices[t]  # 买入比特币
                Portfolios[i, t, 0] = 0  # 现金变为0
                a = 'b'  # 进入比特币状态
            if a == 'b' and EAR[t] < sell:
                Portfolios[i, t, 0] = rate * Portfolios[i, t, 1] * Prices[t]  # 卖出比特币
                Portfolios[i, t, 1] = 0  # 比特币变为0
                a = 'c'  # 进入现金状态
            Portfolios[i, t+1] = Portfolios[i, t]  # 记录当前状态
        Value[i] = Portfolios[i, :, 0] + Portfolios[i, :, 1] * Prices  # 计算总价值
    
    return Portfolios, Value

# 执行回测
Portfolios1, V1 = back_test_pol(hmm, friction, Buy_Price, Sell_Price, BC_Prices)

(4)下面代码用于绘制不同摩擦率下的回测收益图,比较了三种策略的表现:前一天趋势跟随策略(previous day trend follower)、基于HMM优化的买入/卖出策略(back-train optimized HMM buy/sell policy)和简单的比特币投资(Bitcoin investment)。通过对比这些策略在不同摩擦率下的回测收益,用可视化图表展示了各策略在测试期内的表现,并帮助确定最佳的交易策略。

# 计算测试期内的交易次数
ntrades_in_test_period0 = np.sum(Portfolio0[train_end:-1] * Portfolio0[train_end+1:] > 0)

# 绘制图表
plt.semilogy(friction, V0[-1] / V0[train_end] * np.power(1 - friction, ntrades_in_test_period0), label='previous day trend follower')

# 绘制基于HMM优化的买入/卖出策略的回测结果
plt.semilogy(friction, V1[:, -1] / V1[:, train_end], label='back-train optimized HMM buy/sell policy')

# 绘制比特币投资的回测结果
plt.semilogy([0, np.max(friction)], [BC_Prices[-1] / BC_Prices[train_end], BC_Prices[-1] / BC_Prices[train_end]], label='Bitcoin investment')

# 添加图例和标签
plt.legend()
plt.xlabel('friction rate')
plt.ylabel('back testing return')
plt.show()

执行效果如图2-14所示,对上述代码的具体说明如下所示:

  1. ntrades_in_test_period0 计算了在测试期内前一天趋势跟随策略的交易次数。
  2. plt.semilogy 绘制了摩擦率与回测收益之间的关系图。对数刻度用于展示不同摩擦率下的收益。
  3. label 参数为图例提供标签以区分不同策略。

图2-14  三种策略的回测收益图

(5)下面代码用于绘制模拟数据下的投资组合价值随时间变化的图表,比较了使用HMM优化的买入/卖出策略(HMM buy/sell policy)和简单的比特币投资(Bitcoin investment)在0.5%市场摩擦下的表现。

i = 25

# 绘制投资组合价值相对于初始值的变化
plt.plot(range(train_end, ndays), V1[i, train_end:] / V1[i, train_end], label='HMM buy/sell policy')
plt.plot(range(train_end, ndays), BC_Prices[train_end:] / BC_Prices[train_end], label='Bitcoin investment')

# 设置图表标签和标题
plt.xlabel('day')
plt.ylabel('portfolio value')
plt.title('simulation with 0.5% market friction')

# 显示图例
plt.legend()
plt.show()

执行效果如图2-15所示,展示了两种策略的投资组合价值相对于初始值的变化情况,可以帮助我们分析不同策略在给定摩擦率下的效果。

图2-15  在0.5%市场摩擦下的表现

(6)下面代码绘制了在1%市场摩擦条件下,投资组合价值随时间变化的可视化图表。比较了使用HMM优化的买入/卖出策略(HMM buy/sell policy)与简单的比特币投资(Bitcoin investment)的表现。

i = 50

# 绘制投资组合价值相对于初始值的变化
plt.plot(range(train_end, ndays), V1[i, train_end:] / V1[i, train_end], label='HMM buy/sell policy')
plt.plot(range(train_end, ndays), BC_Prices[train_end:] / BC_Prices[train_end], label='Bitcoin investment')

# 设置图表标签和标题
plt.xlabel('day')
plt.ylabel('portfolio value')
plt.title('simulation with 1% market friction')

# 显示图例
plt.legend()
plt.show()

执行效果如图2-16所示

图2-16  在1%市场摩擦下的表现

(7)下面代码绘制了在1.5%市场摩擦条件下,投资组合价值随时间变化的可视化图表,比较了使用HMM优化的买入/卖出策略(HMM buy/sell policy)与简单的比特币投资(Bitcoin investment)的表现。

i = 75

# 绘制投资组合价值相对于初始值的变化
plt.plot(range(train_end, ndays), V1[i, train_end:] / V1[i, train_end], label='HMM buy/sell policy')
plt.plot(range(train_end, ndays), BC_Prices[train_end:] / BC_Prices[train_end], label='Bitcoin investment')

# 设置图表标签和标题
plt.xlabel('day')
plt.ylabel('portfolio value')
plt.title('simulation with 1.5% market friction')

# 显示图例
plt.legend()
plt.show()

执行效果如图2-17所示

图2-17  在1.5%市场摩擦下的表现

2.6.4  结论

事实证明,本项目中实现的交易策略在市场摩擦较小的情况下表现得相当好。隐马尔可夫模型(HMM)能够检测数据中的上涨和下跌趋势,这可以用于做出交易决策。在当前形式下,我们的方法将HMM作为特征提取设备,而不是作为预测模型。如果希望进一步改进模型,以便获得一个可以模拟更接近真实时间序列数据的HMM,并允许一些更有趣的预测模型和/或强化学习。

  1. 一个可能的改进方法是对负对数似然(NLL)优化施加约束或正则化,以尝试获得在隐藏状态之间转换更缓慢的模型。
  2. 也可以尝试使用不同的HMM结构,在使用两个隐藏状态时,模型更倾向于表示增长和快速增长,而不是增长和衰退。如果没有 βri−1 类型的项,HMM的状态过于简单,无法做出精细的决策。

  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农三叔

感谢鼓励

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值