qsq加密货币量化系统: 双均线策略

准备工作

双均线策略资料收集

虽然双均线策略理论简单,但是我还是看了下资料,总结了下别人的策略情况。这里给出两篇。

技术分析入门 —— 双均线策略

介绍:
设置了20日短均线和120日长均线,偏离阈值5%,当短均线高于长均线5%时买入,其余情况都卖出。

5日线10日线交易策略

介绍:
当5日线突破10日线,买入,跌破10日线,卖出

制定策略

看到很多量化的资料中说到,越简单的策略越赚钱,很多大拿都是从复杂策略转向简单策略的。所以我制定了一个简单无比的策略。当3日均线突破5日均线,买入,跌破则卖出。

回测

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 基础库导入

from __future__ import print_function
from __future__ import division

import warnings
warnings.filterwarnings('ignore')
warnings.simplefilter('ignore')

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib as mpl
%matplotlib inline

import os
import sys
# 使用insert 0即只使用github,避免交叉使用了pip安装的abupy,导致的版本不一致问题
sys.path.insert(0, os.path.abspath('../'))
1
2
from datetime import timedelta
from qsq import QsData, QsCrypto, QsAccount, QsSignal, QsPickSignal, QsDrawUtil

获取数据

1
2
3
4
5
data = QsData()
bitcoin = QsCrypto('bitcoin', data.get_coin_df(coin='bitcoin'))
bitcoin.add_window_mean(3)
bitcoin.add_window_mean(5)
bitcoin.crypto_df.tail()

open close high low volume date MarketCap pre_close date_week p_change 3_window_mean 5_window_mean
2019-08-22 10142.52 10131.06 10233.00 9831.46 17,097,508,856 20190822 181,257,125,783 10138.05 3 -0.069 10344.11 10458.84
2019-08-23 10136.31 10407.97 10442.44 10078.19 15,627,023,886 20190823 186,231,409,722 10131.06 4 2.733 10225.69 10471.27
2019-08-24 10407.64 10159.96 10418.02 9982.30 15,451,030,650 20190824 181,813,631,752 10407.97 5 -2.383 10233.00 10320.05
2019-08-25 10160.74 10138.52 10304.62 10008.79 14,153,856,610 20190825 181,450,186,164 10159.96 6 -0.211 10235.48 10195.11
2019-08-26 10126.30 10370.82 10512.33 10126.30 18,438,654,080 20190826 185,625,235,889 10138.52 0 2.291 10223.10 10241.67

我在QsCrypto类中实现了增加均线的api,可以直接调用。

编写信号

如上篇文章所述,我基于信号的回测框架需要用户自己定义信号,所以这里实现对应的类。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class buysignal(QsSignal):
def produce_signal(self,param):
if self.crypto.crypto_df.loc[param]['5_window_mean'] == np.NaN:
return {'mode':0, 'symbol':self.crypto.symbol,'percent':1}
if self.crypto.crypto_df.loc[param]['3_window_mean'] > self.crypto.crypto_df.loc[param]['5_window_mean'] \
and self.crypto.crypto_df.loc[param - timedelta(days=1)]['3_window_mean'] < \
self.crypto.crypto_df.loc[param - timedelta(days=1)]['5_window_mean']:
return {'mode':1, 'symbol':self.crypto.symbol,'percent':1}
else:
return {'mode':0, 'symbol':self.crypto.symbol,'percent':1}

class sellsignal(QsSignal):
def produce_signal(self,param):
if self.crypto.crypto_df.loc[param]['5_window_mean'] == np.NaN:
return {'mode':0, 'symbol':self.crypto.symbol,'percent':1}
if self.crypto.crypto_df.loc[param]['3_window_mean'] < self.crypto.crypto_df.loc[param]['5_window_mean'] \
and self.crypto.crypto_df.loc[param - timedelta(days=1)]['3_window_mean'] > \
self.crypto.crypto_df.loc[param - timedelta(days=1)]['5_window_mean']:
return {'mode':2, 'symbol':self.crypto.symbol,'percent':1}
else:
return {'mode':0, 'symbol':self.crypto.symbol,'percent':1}

开始回测

1
2
3
4
5
6
buy_sig = buysignal(bitcoin)
sell_sig = sellsignal(bitcoin)


myaccount = QsAccount()
QsPickSignal.signal_backtest_percent(myaccount,buy_sig,sell_sig)
2019-09-05 11:36:52,283 - INFO - start back test...
2019-09-05 11:36:52,340 - INFO - 2013-05-06 buy bitcoin 8900.269366652383
2019-09-05 11:36:52,341 - INFO - The asset is 999500.2498750625
//...
2019-09-05 11:37:12,998 - INFO - The asset is 115621945.94236806
2019-09-05 11:37:13,028 - INFO - 2019-08-25 buy bitcoin 11398.5240311641
2019-09-05 11:37:13,030 - INFO - The asset is 115564163.86043786
2019-09-05 11:37:13,055 - INFO - 2019-08-26 sell bitcoin 11398.5240311641
2019-09-05 11:37:13,058 - INFO - The asset is 118152934.97238085
1
QsDrawUtil.plot_dfs({'bitcoin':bitcoin.crypto_df.close, 'asset':myaccount.asset.asset})

我们的策略仍然只是略好于大盘,这其中主要还是18年的大跌没有躲过去。那就让我们再看看最近三个月的回测结果吧。

1
2
3
4
bitcoin = QsCrypto('bitcoin', data.get_coin_df(coin='bitcoin')[-90:])
bitcoin.add_window_mean(3)
bitcoin.add_window_mean(5)
bitcoin.crypto_df.head()

open close high low volume date MarketCap pre_close date_week p_change 3_window_mean 5_window_mean
2019-05-29 8718.59 8659.49 8755.85 8482.73 23,473,479,966 20190529 153,537,047,655 8719.96 2 -0.693 NaN NaN
2019-05-30 8661.76 8319.47 9008.31 8221.27 29,246,528,551 20190530 147,525,141,134 8659.49 3 -3.927 NaN NaN
2019-05-31 8320.29 8574.50 8586.66 8172.55 25,365,190,957 20190531 152,059,886,414 8319.47 4 3.065 8517.82 NaN
2019-06-01 8573.84 8564.02 8625.60 8481.58 22,488,303,544 20190601 151,890,214,310 8574.50 5 -0.122 8486.00 NaN
2019-06-02 8565.47 8742.96 8809.30 8561.24 20,266,216,022 20190602 155,077,231,351 8564.02 6 2.089 8627.16 8572.09
1
2
3
4
5
6
buy_sig = buysignal(bitcoin)
sell_sig = sellsignal(bitcoin)


myaccount = QsAccount()
QsPickSignal.signal_backtest_percent(myaccount,buy_sig,sell_sig)
2019-09-05 11:48:20,617 - INFO - start back test...
2019-09-05 11:48:20,683 - INFO - 2019-06-08 buy bitcoin 125.65802292331941
2019-09-05 11:48:20,684 - INFO - The asset is 999500.2498750625
2019-09-05 11:48:20,711 - INFO - 2019-06-10 sell bitcoin 125.65802292331941
2019-09-05 11:48:20,712 - INFO - The asset is 1004802.9977088528
2019-09-05 11:48:20,736 - INFO - 2019-06-12 buy bitcoin 123.28972598169011
2019-09-05 11:48:20,738 - INFO - The asset is 1004300.8472852102
2019-09-05 11:48:20,839 - INFO - 2019-06-29 sell bitcoin 123.28972598169011
2019-09-05 11:48:20,839 - INFO - The asset is 1473730.2164885385
2019-09-05 11:48:20,882 - INFO - 2019-07-04 buy bitcoin 131.3362400074116
2019-09-05 11:48:20,884 - INFO - The asset is 1472993.7196287243
2019-09-05 11:48:20,910 - INFO - 2019-07-06 sell bitcoin 131.3362400074116
2019-09-05 11:48:20,911 - INFO - The asset is 1471352.7685286058
2019-09-05 11:48:20,938 - INFO - 2019-07-08 buy bitcoin 119.69902716586304
2019-09-05 11:48:20,940 - INFO - The asset is 1470617.4597987065
2019-09-05 11:48:20,984 - INFO - 2019-07-11 stop loss bitcoin 119.69902716586304
2019-09-05 11:48:20,986 - INFO - The asset is 1358940.741631848
2019-09-05 11:48:21,046 - INFO - 2019-07-19 buy bitcoin 128.98076494473176
2019-09-05 11:48:21,048 - INFO - The asset is 1358261.6108264348
2019-09-05 11:48:21,079 - INFO - 2019-07-22 sell bitcoin 128.98076494473176
2019-09-05 11:48:21,080 - INFO - The asset is 1333395.2085876507
2019-09-05 11:48:21,135 - INFO - 2019-07-31 buy bitcoin 132.1413579682745
2019-09-05 11:48:21,136 - INFO - The asset is 1332728.844165568
2019-09-05 11:48:21,201 - INFO - 2019-08-11 sell bitcoin 132.1413579682745
2019-09-05 11:48:21,202 - INFO - The asset is 1521980.1391011204
2019-09-05 11:48:21,251 - INFO - 2019-08-18 buy bitcoin 147.03725753096685
2019-09-05 11:48:21,252 - INFO - The asset is 1521219.5293364523
2019-09-05 11:48:21,316 - INFO - 2019-08-22 sell bitcoin 147.03725753096685
2019-09-05 11:48:21,317 - INFO - The asset is 1488898.4566425364
2019-09-05 11:48:21,346 - INFO - 2019-08-25 buy bitcoin 146.78221076180841
2019-09-05 11:48:21,347 - INFO - The asset is 1488154.3794528102
2019-09-05 11:48:21,368 - INFO - 2019-08-26 sell bitcoin 146.78221076180841
2019-09-05 11:48:21,373 - INFO - The asset is 1521490.7610692717
1
QsDrawUtil.plot_dfs({'bitcoin':bitcoin.crypto_df.close, 'asset':myaccount.asset.asset})

可见,在最近三个月的回测中,我们获得了约1.5倍的收益,大盘收益约为1.3,可见我们并没有遥遥领先。

对以太坊进行回测

以太坊也是我个人看好并持有的币种,所以我决定对其进行一个回测。
1
2
3
4
ethereum = QsCrypto('ethereum', data.get_coin_df(coin='ethereum'))
ethereum.add_window_mean(3)
ethereum.add_window_mean(5)
ethereum.crypto_df.head()

open close high low volume date MarketCap pre_close date_week p_change 3_window_mean 5_window_mean
2015-08-07 2.830000 2.770000 3.540000 2.520000 164,329 20150807 166,610,555 NaN 4 NaN NaN NaN
2015-08-08 2.790000 0.753325 2.800000 0.714725 674,188 20150808 45,486,894 2.770000 5 -72.804 NaN NaN
2015-08-09 0.706136 0.701897 0.879810 0.629191 532,170 20150809 42,399,573 0.753325 6 -6.827 1.41 NaN
2015-08-10 0.713989 0.708448 0.729854 0.636546 405,283 20150810 42,818,364 0.701897 0 0.933 0.72 NaN
2015-08-11 0.708087 1.070000 1.130000 0.663235 1,463,100 20150811 64,569,288 0.708448 1 51.034 0.83 1.2
1
2
3
4
5
buy_sig = buysignal(ethereum)
sell_sig = sellsignal(ethereum)

myaccount = QsAccount()
QsPickSignal.signal_backtest_percent(myaccount,buy_sig,sell_sig)
2019-09-05 12:05:37,245 - INFO - start back test...
2019-09-05 12:05:37,291 - INFO - 2015-08-12 buy ethereum 819262.4998975922
2019-09-05 12:05:37,292 - INFO - The asset is 999500.2498750625
2019-09-05 12:05:37,337 - INFO - 2015-08-17 sell ethereum 819262.4998975922
2019-09-05 12:05:37,339 - INFO - The asset is 982623.4423771721
2019-09-05 12:05:37,365 - INFO - 2015-08-21 buy ethereum 701523.1258493412
2019-09-05 12:05:37,369 - INFO - The asset is 982132.3761890776
2019-09-05 12:05:37,404 - INFO - 2015-08-24 sell ethereum 701523.1258493412
2019-09-05 12:05:37,406 - INFO - The asset is 862442.0080722924
2019-09-05 12:05:37,485 - INFO - 2015-09-06 buy ethereum 663085.3865930822
//...
2019-09-05 12:05:49,409 - INFO - The asset is 55316698.07364422
2019-09-05 12:05:49,452 - INFO - 2019-08-22 sell ethereum 284419.2404424095
2019-09-05 12:05:49,453 - INFO - The asset is 54390724.30720929
2019-09-05 12:05:49,473 - INFO - 2019-08-24 buy ethereum 284194.3778343945
2019-09-05 12:05:49,476 - INFO - The asset is 54363542.535941325
2019-09-05 12:05:49,501 - INFO - 2019-08-26 sell ethereum 284194.3778343945
2019-09-05 12:05:49,503 - INFO - The asset is 53665997.382350035
1
QsDrawUtil.plot_dfs({'ethereum':ethereum.crypto_df.close, 'asset':myaccount.asset.asset})

1
myaccount.asset.asset[-1]/myaccount.asset.asset[0]
53.665997382350035

可见收益实在太惨,输给了大盘。但是却发现这个策略在18年第一次大跌的时候顽强挺住,直到第二次大跌才崩盘。我们再看下最近3个月的效果。

1
2
3
4
ethereum = QsCrypto('ethereum', data.get_coin_df(coin='ethereum')[-90:])
ethereum.add_window_mean(3)
ethereum.add_window_mean(5)
ethereum.crypto_df.head()

open close high low volume date MarketCap pre_close date_week p_change 3_window_mean 5_window_mean
2019-05-29 271.78 269.46 273.76 263.09 9,819,132,174 20190529 28,636,457,373 271.77 2 -0.850 NaN NaN
2019-05-30 269.55 255.86 287.20 247.35 13,604,268,584 20190530 27,194,892,741 269.46 3 -5.047 NaN NaN
2019-05-31 256.02 268.11 268.66 249.11 11,255,023,515 20190531 28,501,098,831 255.86 4 4.788 264.48 NaN
2019-06-01 268.43 265.39 273.56 263.52 9,942,869,852 20190601 28,215,330,784 268.11 5 -1.015 263.12 NaN
2019-06-02 265.51 270.23 272.81 265.04 8,744,111,713 20190602 28,732,949,885 265.39 6 1.824 267.91 265.81
1
2
3
4
5
buy_sig = buysignal(ethereum)
sell_sig = sellsignal(ethereum)

myaccount = QsAccount()
QsPickSignal.signal_backtest_percent(myaccount,buy_sig,sell_sig)
2019-09-05 14:26:35,567 - INFO - start back test...
2019-09-05 14:26:35,627 - INFO - 2019-06-07 buy ethereum 3983.1835566694394
2019-09-05 14:26:35,628 - INFO - The asset is 999500.2498750625
2019-09-05 14:26:35,654 - INFO - 2019-06-09 sell ethereum 3983.1835566694394
2019-09-05 14:26:35,658 - INFO - The asset is 927976.0350964677
2019-09-05 14:26:35,701 - INFO - 2019-06-12 buy ethereum 3555.0489802874254
2019-09-05 14:26:35,705 - INFO - The asset is 927512.2789569893
2019-09-05 14:26:35,762 - INFO - 2019-06-20 sell ethereum 3555.0489802874254
2019-09-05 14:26:35,763 - INFO - The asset is 965423.8545401216
2019-09-05 14:26:35,779 - INFO - 2019-06-21 buy ethereum 3271.985974867578
2019-09-05 14:26:35,781 - INFO - The asset is 964941.3838481975
2019-09-05 14:26:35,845 - INFO - 2019-06-28 sell ethereum 3271.985974867578
2019-09-05 14:26:35,846 - INFO - The asset is 1017831.0248605574
2019-09-05 14:26:35,895 - INFO - 2019-07-04 buy ethereum 3575.5741729183123
2019-09-05 14:26:35,896 - INFO - The asset is 1017322.3636787181
2019-09-05 14:26:35,917 - INFO - 2019-07-05 sell ethereum 3575.5741729183123
2019-09-05 14:26:35,921 - INFO - The asset is 1029250.4791195737
2019-09-05 14:26:35,956 - INFO - 2019-07-08 buy ethereum 3284.073778336925
2019-09-05 14:26:35,958 - INFO - The asset is 1028736.1110640417
2019-09-05 14:26:35,986 - INFO - 2019-07-10 stop loss ethereum 3284.073778336925
2019-09-05 14:26:35,989 - INFO - The asset is 951905.2050198495
2019-09-05 14:26:36,063 - INFO - 2019-07-19 buy ethereum 4298.691954433254
2019-09-05 14:26:36,065 - INFO - The asset is 951429.4902747122
2019-09-05 14:26:36,105 - INFO - 2019-07-23 sell ethereum 4298.691954433254
2019-09-05 14:26:36,106 - INFO - The asset is 914003.5090968529
2019-09-05 14:26:36,136 - INFO - 2019-07-26 buy ethereum 4159.480652592944
2019-09-05 14:26:36,139 - INFO - The asset is 913546.7357289884
2019-09-05 14:26:36,160 - INFO - 2019-07-27 stop loss ethereum 4159.480652592944
2019-09-05 14:26:36,161 - INFO - The asset is 862286.5232132255
2019-09-05 14:26:36,204 - INFO - 2019-07-31 buy ethereum 3941.7132193712227
2019-09-05 14:26:36,207 - INFO - The asset is 861855.5954155178
2019-09-05 14:26:36,264 - INFO - 2019-08-08 sell ethereum 3941.7132193712227
2019-09-05 14:26:36,265 - INFO - The asset is 870446.6776285339
2019-09-05 14:26:36,318 - INFO - 2019-08-13 buy ethereum 4168.519341634984
2019-09-05 14:26:36,321 - INFO - The asset is 870011.6717926377
2019-09-05 14:26:36,345 - INFO - 2019-08-14 sell ethereum 4168.519341634984
2019-09-05 14:26:36,350 - INFO - The asset is 777498.4506453334
2019-09-05 14:26:36,408 - INFO - 2019-08-18 buy ethereum 3995.6290590646545
2019-09-05 14:26:36,410 - INFO - The asset is 777109.8956974847
2019-09-05 14:26:36,473 - INFO - 2019-08-22 sell ethereum 3995.6290590646545
2019-09-05 14:26:36,474 - INFO - The asset is 764101.466016905
2019-09-05 14:26:36,498 - INFO - 2019-08-24 buy ethereum 3992.470104102662
2019-09-05 14:26:36,500 - INFO - The asset is 763719.6062137982
2019-09-05 14:26:36,540 - INFO - 2019-08-26 sell ethereum 3992.470104102662
2019-09-05 14:26:36,541 - INFO - The asset is 753920.2280797319
1
QsDrawUtil.plot_dfs({'ethereum':ethereum.crypto_df.close, 'asset':myaccount.asset.asset})

由此可见,这个策略似乎并没有太大的用处。这也是没有办法的事,19年的大涨都体现在bitcoin上了,其他的币没啥起色。当然了,这或许是因为我的参数不对的缘故。

总结

这篇小研究中,我们实现了一个简单的双均线策略,通过研究发现,我们的参数和方法并没有获得比上一个择时策略更好的效果,但是这其中存在的不足之处在于我没有好好研究其中的参数设置,后面我会尝试进行一个优化。这其中需要我们设置一个对策略的评分体系和对最优参数的一个搜寻方法。

交流方式

email: xudong_shao#hotmail.com
qq群: 742593185