Skip to content

Commit

Permalink
第24节 比特币vs黄金,莱特币vs白银
Browse files Browse the repository at this point in the history
  • Loading branch information
bbfamily committed Aug 26, 2017
1 parent f00a070 commit dd486c4
Show file tree
Hide file tree
Showing 7 changed files with 1,753 additions and 28 deletions.
129 changes: 129 additions & 0 deletions abupy/FactorBuyBu/ABuFactorBuyDemo.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
from __future__ import print_function
from __future__ import division

import numpy as np
import pandas as pd

from .ABuFactorBuyBase import AbuFactorBuyBase, BuyCallMixin
from .ABuFactorBuyBreak import AbuFactorBuyBreak
from ..TLineBu.ABuTL import AbuTLine
Expand Down Expand Up @@ -206,3 +209,129 @@ def make_ump_block_decision(self, ml_feature_dict):
if result == -1:
return True
return False


class AbuBTCDayBuy(AbuFactorBuyBase, BuyCallMixin):
"""
比特币日交易策略:
1. 买入条件1: 当日这100个股票60%以上都是上涨的
2. 买入条件2: 使用在第12节:机器学习与比特币示例中编写的:信号发出今天比特币会有大行情
"""

def _init_self(self, **kwargs):
from ..UtilBu.ABuProgress import AbuProgress
from ..MarketBu import ABuSymbolPd

# 市场中与btc最相关的top个股票
self.btc_similar_top = kwargs.pop('btc_similar_top')
# 超过多少个相关股票今天趋势相同就买入
self.btc_vote_val = kwargs.pop('btc_vote_val', 0.60)
self.pg = AbuProgress(len(self.kl_pd), 0, 'btc buy day')

def _collect_kl(sim_line):
"""在初始化中将所有相关股票的对应时间的k线数据进行收集"""
start = self.kl_pd.iloc[0].date
end = self.kl_pd.iloc[-1].date
kl = ABuSymbolPd.make_kl_df(sim_line.symbol, start=start, end=end)
self.kl_dict[sim_line.symbol] = kl

self.kl_dict = {}
# k线数据进行收集到类字典对象self.kl_dict中
self.btc_similar_top.apply(_collect_kl, axis=1)

# noinspection PyUnresolvedReferences
def fit_day(self, today):
"""
:param today: 当前驱动的交易日金融时间序列数据
:return:
"""
self.pg.show()

# key是金融时间序列索引
day_ind = int(today.key)
# 忽略不符合买入的天(统计周期内前两天及最后一天),因为btc的机器学习特证需要三天交易数据
if day_ind < 2 or day_ind >= self.kl_pd.shape[0] - 1:
return None

# 今天,昨天,前天三天的交易数据进行特证转换
btc = self.kl_pd[day_ind - 2:day_ind + 1]
# 三天的交易数据进行转换后得到btc_today_x
btc_today_x = self.make_btc_today(btc)

# btc_ml并没有在这里传入,实际如果要使用,需要对外部的btc_ml进行本地序列化后,构造读取本地
# 买入条件2: 使用在第12节:机器学习与比特币示例中编写的:信号发出今天比特币会有大行情
if btc_ml.predict(btc_today_x):
# 买入条件1: 当日这100个股票60%以上都是上涨的
vote_val = self.similar_predict(today.date)
if vote_val > self.btc_vote_val:
return self.make_buy_order(day_ind - 1)

# noinspection PyUnresolvedReferences
def make_btc_today(self, sib_btc):
"""构造比特币三天数据特证"""
from ..UtilBu import ABuScalerUtil

sib_btc['big_wave'] = (sib_btc.high - sib_btc.low) / sib_btc.pre_close > 0.55
sib_btc['big_wave'] = sib_btc['big_wave'].astype(int)
sib_btc_scale = ABuScalerUtil.scaler_std(
sib_btc.filter(['open', 'close', 'high', 'low', 'volume', 'pre_close',
'ma5', 'ma10', 'ma21', 'ma60', 'atr21', 'atr14']))
# 把标准化后的和big_wave,date_week连接起来
sib_btc_scale = pd.concat([sib_btc['big_wave'], sib_btc_scale, sib_btc['date_week']], axis=1)

# 抽取第一天,第二天的大多数特征分别改名字以one,two为特征前缀,如:one_open,one_close,two_ma5,two_high.....
a0 = sib_btc_scale.iloc[0].filter(['open', 'close', 'high', 'low', 'volume', 'pre_close',
'ma5', 'ma10', 'ma21', 'ma60', 'atr21', 'atr14', 'date_week'])
a0.rename(index={'open': 'one_open', 'close': 'one_close', 'high': 'one_high', 'low': 'one_low',
'volume': 'one_volume', 'pre_close': 'one_pre_close',
'ma5': 'one_ma5', 'ma10': 'one_ma10', 'ma21': 'one_ma21',
'ma60': 'one_ma60', 'atr21': 'one_atr21', 'atr14': 'one_atr14',
'date_week': 'one_date_week'}, inplace=True)

a1 = sib_btc_scale.iloc[1].filter(['open', 'close', 'high', 'low', 'volume', 'pre_close',
'ma5', 'ma10', 'ma21', 'ma60', 'atr21', 'atr14', 'date_week'])
a1.rename(index={'open': 'two_open', 'close': 'two_close', 'high': 'two_high', 'low': 'two_low',
'volume': 'two_volume', 'pre_close': 'two_pre_close',
'ma5': 'two_ma5', 'ma10': 'two_ma10', 'ma21': 'two_ma21',
'ma60': 'two_ma60', 'atr21': 'two_atr21', 'atr14': 'two_atr14',
'date_week': 'two_date_week'}, inplace=True)
# 第三天的特征只使用'open', 'low', 'pre_close', 'date_week',该名前缀today,如today_open,today_date_week
a2 = sib_btc_scale.iloc[2].filter(['big_wave', 'open', 'low', 'pre_close', 'date_week'])
a2.rename(index={'open': 'today_open', 'low': 'today_low',
'pre_close': 'today_pre_close',
'date_week': 'today_date_week'}, inplace=True)
# 将抽取改名字后的特征连接起来组合成为一条新数据,即3天的交易数据特征->1条新的数据
btc_today = pd.DataFrame(pd.concat([a0, a1, a2], axis=0)).T

# 开始将周几进行离散处理
dummies_week_col = btc_ml.df.filter(regex='(^one_date_week_|^two_date_week_|^today_date_week_)').columns
dummies_week_df = pd.DataFrame(np.zeros((1, len(dummies_week_col))), columns=dummies_week_col)

# 手动修改每一天的one hot
one_day_key = 'one_date_week_{}'.format(btc_today.one_date_week.values[0])
dummies_week_df[one_day_key] = 1
two_day_key = 'two_date_week_{}'.format(btc_today.two_date_week.values[0])
dummies_week_df[two_day_key] = 1
today_day_key = 'today_date_week_{}'.format(btc_today.today_date_week.values[0])
dummies_week_df[today_day_key] = 1
btc_today.drop(['one_date_week', 'two_date_week', 'today_date_week'], inplace=True, axis=1)
btc_today = pd.concat([btc_today, dummies_week_df], axis=1)
return btc_today.as_matrix()[:, 1:]

def similar_predict(self, today_date):
"""与比特币在市场中最相关的top100个股票已各自今天的涨跌结果进行投票"""
def _predict_vote(sim_line, _today_date):
kl = self.kl_dict[sim_line.symbol]
if kl is None:
return -1 * sim_line.vote_direction > 0
kl_today = kl[kl.date == _today_date]
if kl_today is None or kl_today.empty:
return -1 * sim_line.vote_direction > 0
# 需要 * sim_line.vote_direction,因为负相关的存在
return kl_today.p_change.values[0] * sim_line.vote_direction > 0

vote_result = self.btc_similar_top.apply(_predict_vote, axis=1, args={today_date, })
# 将所有投票结果进行统计,得到与比特币最相关的这top100个股票的今天投票结果
vote_val = 1 - vote_result.value_counts()[False] / vote_result.value_counts().sum()
return vote_val
41 changes: 41 additions & 0 deletions abupy/FactorSellBu/ABuFactorSellNDay.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# -*- encoding:utf-8 -*-
"""
卖出择时示例因子:n日卖出策略,不管什么结果,买入后只持有N天
"""

from __future__ import absolute_import
from __future__ import print_function
from __future__ import division

from .ABuFactorSellBase import AbuFactorSellBase, filter_sell_order, skip_last_day, ESupportDirection

__author__ = '阿布'
__weixin__ = 'abu_quant'


class AbuFactorSellNDay(AbuFactorSellBase):
"""n日卖出策略,不管交易现在什么结果,买入后只持有N天"""

def _init_self(self, **kwargs):
"""kwargs中可以包含: 参数sell_n:代表买入后持有的天数,默认1天"""
self.sell_n = kwargs.pop('sell_n', 1)
self.sell_type_extra = '{}:sell_n={}'.format(self.__class__.__name__, self.sell_n)

def support_direction(self):
"""因子支持两个方向"""
return [ESupportDirection.DIRECTION_CAll.value, ESupportDirection.DIRECTION_PUT.value]

@skip_last_day
@filter_sell_order
def fit_day(self, today, orders):
"""
:param today: 当前驱动的交易日金融时间序列数据
:param orders: 买入择时策略中生成的订单序列
:return:
"""
for order in orders:
# 将单子的持有天数进行增加
order.keep_days += 1
if order.keep_days >= self.sell_n:
# 只要超过self.sell_n即卖出
order.fit_sell_order(int(today.key), self)
2 changes: 2 additions & 0 deletions abupy/FactorSellBu/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from .ABuFactorAtrNStop import AbuFactorAtrNStop
from .ABuFactorCloseAtrNStop import AbuFactorCloseAtrNStop
from .ABuFactorSellBreak import AbuFactorSellBreak
from .ABuFactorSellNDay import AbuFactorSellNDay
# noinspection all
from . import ABuFS as fs

Expand All @@ -17,6 +18,7 @@
'AbuFactorAtrNStop',
'AbuFactorCloseAtrNStop',
'AbuFactorSellBreak',
'AbuFactorSellNDay',

'fs'
]
69 changes: 42 additions & 27 deletions abupy/MLBu/ABuMLPd.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,20 +158,34 @@ class BtcBigWaveClf(AbuMLPd):
做出这个判断的依据里有一条即是今天的波动需要足够大
"""

def make_xy(self, **kwarg):

# 从沙盒中读取测试数据
ABuEnv.enable_example_env_ipython()
btc = ABuSymbolPd.make_kl_df('btc', start='2013-09-01', end='2017-07-26')
ABuEnv.disable_example_env_ipython()
def __init__(self, **kwarg):
"""
如果传递了btc数据,说明不是运行:
12-机器学习与比特币示例(ABU量化使用文档)
"""
self.btc = kwarg.pop('btc', None)
super(BtcBigWaveClf, self).__init__(**kwarg)

def make_xy(self, **kwarg):
if self.btc is None:
# 从沙盒中读取测试数据
ABuEnv.enable_example_env_ipython()
btc = ABuSymbolPd.make_kl_df('btc', start='2013-09-01', end='2017-07-26')
ABuEnv.disable_example_env_ipython()
else:
btc = self.btc
# .055的日震荡幅度可以成做大波动的交易对比特币来说,下面对数据添加新列big_wave
btc['big_wave'] = (btc.high - btc.low) / btc.pre_close > 0.055
btc['big_wave'] = btc['big_wave'].astype(int)

# 首先切割训练集和测试集,保留最后60天走势数据做为测试集数据
btc_train_raw = btc[:-60]
btc_test_raw = btc[-60:]
if self.btc is None:
# 如果是12-机器学习与比特币示例(ABU量化使用文档),保留60天数据
# 首先切割训练集和测试集,保留最后60天走势数据做为测试集数据
btc_train_raw = btc[:-60]
btc_test_raw = btc[-60:]
else:
btc_train_raw = btc
btc_test_raw = None

# 下面为训练集和测试集数据都加上5,10,21,60日均线特征
def calc_ma(tc, p_ma):
Expand All @@ -180,7 +194,8 @@ def calc_ma(tc, p_ma):

for ma in [5, 10, 21, 60]:
calc_ma(btc_train_raw, ma)
calc_ma(btc_test_raw, ma)
if btc_test_raw is not None:
calc_ma(btc_test_raw, ma)
# 下面使用训练集数据btc_train_raw做为参数抽取组合特征,重新组合好的特征
btc_train0 = self.btc_siblings_df(btc_train_raw)
# 由于每3条连续交易日数据组合成一个特征,只要向前跳一条数据进行特征组合抽取即可以得到另一组新特征
Expand All @@ -194,29 +209,29 @@ def calc_ma(tc, p_ma):
dummies_two_week = pd.get_dummies(btc_train['two_date_week'], prefix='two_date_week')
dummies_today_week = pd.get_dummies(btc_train['today_date_week'], prefix='today_date_week')
btc_train.drop(['one_date_week', 'two_date_week', 'today_date_week'], inplace=True, axis=1)

# make_xy中需要确定self.df
self.df = pd.concat([btc_train, dummies_one_week, dummies_two_week, dummies_today_week], axis=1)
# make_xy中需要确定x, y
train_matrix = btc_train.as_matrix()
train_matrix = self.df.as_matrix()
self.y = train_matrix[:, 0]
self.x = train_matrix[:, 1:]

# 下面将前面保留切割的60条测试数据进行特征抽取组合,方式和抽取训练集时一样
btc_test0 = self.btc_siblings_df(btc_test_raw)
btc_test1 = self.btc_siblings_df(btc_test_raw[1:])
btc_test2 = self.btc_siblings_df(btc_test_raw[2:])
btc_test = pd.concat([btc_test0, btc_test1, btc_test2])
btc_test.index = np.arange(0, btc_test.shape[0])
dummies_one_week = pd.get_dummies(btc_test['one_date_week'], prefix='one_date_week')
dummies_two_week = pd.get_dummies(btc_test['two_date_week'], prefix='two_date_week')
dummies_today_week = pd.get_dummies(btc_test['today_date_week'], prefix='today_date_week')
btc_test.drop(['one_date_week', 'two_date_week', 'today_date_week'], inplace=True, axis=1)
self.btc_test = pd.concat([btc_test, dummies_one_week, dummies_two_week, dummies_today_week], axis=1)
# 测试集数据构建
matrix_test = btc_test.as_matrix()
self.y_test = matrix_test[:, 0]
self.x_test = matrix_test[:, 1:]
if btc_test_raw is not None:
# 下面将前面保留切割的60条测试数据进行特征抽取组合,方式和抽取训练集时一样
btc_test0 = self.btc_siblings_df(btc_test_raw)
btc_test1 = self.btc_siblings_df(btc_test_raw[1:])
btc_test2 = self.btc_siblings_df(btc_test_raw[2:])
btc_test = pd.concat([btc_test0, btc_test1, btc_test2])
btc_test.index = np.arange(0, btc_test.shape[0])
dummies_one_week = pd.get_dummies(btc_test['one_date_week'], prefix='one_date_week')
dummies_two_week = pd.get_dummies(btc_test['two_date_week'], prefix='two_date_week')
dummies_today_week = pd.get_dummies(btc_test['today_date_week'], prefix='today_date_week')
btc_test.drop(['one_date_week', 'two_date_week', 'today_date_week'], inplace=True, axis=1)
self.btc_test = pd.concat([btc_test, dummies_one_week, dummies_two_week, dummies_today_week], axis=1)
# 测试集数据构建
matrix_test = self.btc_test.as_matrix()
self.y_test = matrix_test[:, 0]
self.x_test = matrix_test[:, 1:]

# noinspection PyMethodMayBeStatic
def btc_siblings_df(self, btc_raw):
Expand Down
20 changes: 20 additions & 0 deletions abupy/RomDataBu/futures_gb.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
,symbol,product,min_deposit,min_unit,exchange
0,NID,伦敦镍,0.07,6,LME
1,PBD,伦敦铅,0.1,25,LME
2,SND,伦敦锡,0.05,5,LME
3,ZSD,伦敦锌,0.1,25,LME
4,AHD,伦敦铝,0.08,25,LME
5,CAD,伦敦铜,0.08,25,LME
6,XAU,伦敦金,0.1,1,LME
7,XAG,伦敦银,0.1,100,LME
8,XPT,伦敦铂金,0.1,1,LME
9,S,美黄豆,0.1,5000,CBOT
10,W,美小麦,0.1,5000,CBOT
11,C,美玉米,0.1,5000,CBOT
12,BO,美豆油,0.1,60000,CBOT
13,SM,美豆粕,0.1,100,CBOT
14,HG,纽约铜,0.1,25000,NYMEX
15,SI,纽约白银,0.08,5000,NYMEX
16,GC,纽约黄金,0.08,100,NYMEX
17,CL,纽约原油,0.07,1000,NYMEX
18,NG,纽约天然气,0.07,10000,NYMEX
5 changes: 4 additions & 1 deletion abupy/TradeBu/ABuOrder.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class AbuOrder(object):
# 多个因子买入条件可能生成几百万个order对象使用__slots__降低内存消耗
__slots__ = ('order_deal', 'buy_symbol', 'buy_date', 'buy_factor', 'buy_price', 'buy_cnt', 'buy_pos', 'sell_date',
'buy_type_str', 'expect_direction',
'sell_type', 'sell_price', 'sell_type_extra', 'ml_features')
'sell_type', 'keep_days', 'sell_price', 'sell_type_extra', 'ml_features')

def __init__(self):
"""初始设置只需要将order_deal设置未成交状态"""
Expand Down Expand Up @@ -162,6 +162,9 @@ def fit_buy_order(self, day_ind, factor_object):
self.sell_date = None
# 订单卖出类型,keep:持有
self.sell_type = 'keep'
# 交易日持有天数
self.keep_days = 0

# 订单卖出价格
self.sell_price = None
# 订单卖出额外信息
Expand Down
Loading

0 comments on commit dd486c4

Please sign in to comment.