Skip to content

Commit

Permalink
sns统一env设置
Browse files Browse the repository at this point in the history
grid search重构
资金管理界面ui
沙盒数据默认csv
仓位管理重构
bbfamily committed Oct 9, 2017
1 parent 65506b6 commit b5ec880
Showing 87 changed files with 1,489 additions and 671 deletions.
12 changes: 6 additions & 6 deletions abupy/AlphaBu/ABuPickTimeExecute.py
Original file line number Diff line number Diff line change
@@ -80,7 +80,7 @@ def _do_pick_time_work(capital, buy_factors, sell_factors, kl_pd, benchmark, dra
@add_process_env_sig
def do_symbols_with_same_factors(target_symbols, benchmark, buy_factors, sell_factors, capital,
apply_capital=True, kl_pd_manager=None,
show=False, back_target_symbols=None, func_factors=None):
show=False, back_target_symbols=None, func_factors=None, show_progress=True):
"""
输入为多个择时交易对象,以及相同的择时买入,卖出因子序列,对多个交易对象上实施相同的因子
:param target_symbols: 多个择时交易对象序列
@@ -93,7 +93,7 @@ def do_symbols_with_same_factors(target_symbols, benchmark, buy_factors, sell_fa
:param show: 是否显示每个交易对象的交易细节
:param back_target_symbols: 补位targetSymbols为了忽略网络问题及数据不足导致的问题
:param func_factors: funcFactors在内层解开factors dicts为了do_symbols_with_diff_factors
:return:
:param show_progress: 进度条显示,默认True
"""
if kl_pd_manager is None:
kl_pd_manager = AbuKLManager(benchmark, capital)
@@ -103,9 +103,8 @@ def _batch_symbols_with_same_factors(p_buy_factors, p_sell_factors):
r_action_pd = None
r_all_fit_symbols_cnt = 0
# 启动多进程进度显示AbuMulPidProgress
with AbuMulPidProgress(len(target_symbols), 'pick times complete') as progress:
with AbuMulPidProgress(len(target_symbols), 'pick times complete', show_progress=show_progress) as progress:
for epoch, target_symbol in enumerate(target_symbols):

# 如果symbol只有一个就不show了,留给下面_do_pick_time_work中show_pg内部显示进度
if len(target_symbols) > 1:
# 如果要绘制交易细节就不要clear了
@@ -117,7 +116,8 @@ def _batch_symbols_with_same_factors(p_buy_factors, p_sell_factors):
try:
kl_pd = kl_pd_manager.get_pick_time_kl_pd(target_symbol)
ret, fit_error = _do_pick_time_work(capital, p_buy_factors, p_sell_factors, kl_pd, benchmark,
draw=show, show_info=show, show_pg=len(target_symbols) == 1)
draw=show, show_info=show,
show_pg=(len(target_symbols) == 1 and show_progress))
except Exception as e:
logging.exception(e)
continue
@@ -158,7 +158,7 @@ def _batch_symbols_with_same_factors(p_buy_factors, p_sell_factors):
orders_pd = orders_pd.sort_values(['buy_date'])
if apply_capital:
# 如果非多进程环境下开始融合资金对象
ABuTradeExecute.apply_action_to_capital(capital, action_pd, kl_pd_manager)
ABuTradeExecute.apply_action_to_capital(capital, action_pd, kl_pd_manager, show_progress=show_progress)

return orders_pd, action_pd, all_fit_symbols_cnt

10 changes: 6 additions & 4 deletions abupy/AlphaBu/ABuPickTimeMaster.py
Original file line number Diff line number Diff line change
@@ -31,7 +31,8 @@ def do_symbols_with_same_factors_process(cls, target_symbols, benchmark, buy_fac
kl_pd_manager=None,
n_process_kl=ABuEnv.g_cpu_cnt * 2 if ABuEnv.g_is_mac_os
else ABuEnv.g_cpu_cnt,
n_process_pick_time=ABuEnv.g_cpu_cnt):
n_process_pick_time=ABuEnv.g_cpu_cnt,
show_progress=True):
"""
将多个交易对象拆解为多份交易对象序列,多任务并行完成择时工作
:param target_symbols: 多个择时交易对象序列
@@ -42,7 +43,7 @@ def do_symbols_with_same_factors_process(cls, target_symbols, benchmark, buy_fac
:param kl_pd_manager: 金融时间序列管理对象,AbuKLManager实例
:param n_process_kl: 控制金融时间序列管理对象内部启动n_process_kl进程获取金融序列数据
:param n_process_pick_time: 控制择时操作并行任务数量
:return:
:param show_progress: 显示进度条,透传do_symbols_with_same_factors,默认True
"""

if kl_pd_manager is None:
@@ -74,7 +75,8 @@ def do_symbols_with_same_factors_process(cls, target_symbols, benchmark, buy_fac
# 每个并行的进程通过do_symbols_with_same_factors及自己独立的子序列独立工作,注意kl_pd_manager装载了所有需要的数据
out = parallel(delayed(do_symbols_with_same_factors)(choice_symbols, benchmark, buy_factors, sell_factors,
capital, apply_capital=False,
kl_pd_manager=kl_pd_manager, env=p_nev)
kl_pd_manager=kl_pd_manager, env=p_nev,
show_progress=show_progress)
for choice_symbols in process_symbols)
# 择时并行结束后恢复之前的数据获取模式
ABuEnv.g_data_fetch_mode = tmp_fetch_mode
@@ -96,6 +98,6 @@ def do_symbols_with_same_factors_process(cls, target_symbols, benchmark, buy_fac
# noinspection PyUnresolvedReferences
orders_pd = orders_pd.sort_values(['buy_date'])
# 最后将所有的action作用在资金上,生成资金时序,及判断是否能买入
ABuTradeExecute.apply_action_to_capital(capital, action_pd, kl_pd_manager)
ABuTradeExecute.apply_action_to_capital(capital, action_pd, kl_pd_manager, show_progress=show_progress)

return orders_pd, action_pd, all_fit_symbols_cnt
2 changes: 1 addition & 1 deletion abupy/AlphaBu/ABuPickTimeWorker.py
Original file line number Diff line number Diff line change
@@ -126,7 +126,7 @@ def _day_task(self, today):
# 优先执行买入择时因子专属卖出择时因子,不受买入因子是否被锁的影响
self._task_attached_sell(today, how='day')

# 注意回测模式下始终非高频,非当日买菜,不区分美股,A股市场,卖出因子要先于买入因子的执行
# 注意回测模式下始终非高频,非当日买卖,不区分美股,A股市场,卖出因子要先于买入因子的执行
for sell_factor in self.sell_factors:
# 迭代卖出因子,每个卖出因子针对今日交易数据,已经所以交易单进行择时
sell_factor.read_fit_day(today, self.orders)
23 changes: 16 additions & 7 deletions abupy/BetaBu/ABuAtrPosition.py
Original file line number Diff line number Diff line change
@@ -8,12 +8,15 @@
from __future__ import print_function

from .ABuPositionBase import AbuPositionBase
from . import ABuPositionBase

__author__ = '阿布'
__weixin__ = 'abu_quant'

"""默认0.1即10% 外部可通过如:abupy.beta.atr.g_atr_pos_base = 0.01修改仓位基础比例"""
"""
默认0.1即10% 外部可通过如:abupy.beta.atr.g_atr_pos_base = 0.01修改仓位基础配比
需要注意外部其它自定义仓位管理类不要随意使用模块全局变量,AbuAtrPosition特殊因为注册
在ABuEnvProcess中在多进程启动时拷贝了模块全局设置内存
"""
g_atr_pos_base = 0.1


@@ -28,19 +31,25 @@ def fit_position(self, factor_object):
fit_position计算的结果是买入多少个单位(股,手,顿,合约)
计算:(常数价格 / 买入价格)* 当天交易日atr21
:param factor_object: ABuFactorBuyBases实例对象
:return:买入多少个单位(股,手,顿,合约)
:return: 买入多少个单位(股,手,顿,合约)
"""
std_atr = (AbuAtrPosition.s_atr_base_price / self.bp) * self.kl_pd_buy['atr21']
std_atr = (self.atr_base_price / self.bp) * self.kl_pd_buy['atr21']

"""
对atr 进行限制 避免由于股价波动过小,导致
atr小,产生大量买单,实际上针对这种波动异常(过小,过大)的股票
需要有其它的筛选过滤策略, 选股的时候取0.5,这样最大取两倍g_atr_pos_base
"""
atr_wv = AbuAtrPosition.s_std_atr_threshold if std_atr < AbuAtrPosition.s_std_atr_threshold else std_atr
atr_wv = self.std_atr_threshold if std_atr < self.std_atr_threshold else std_atr
# 计算出仓位比例
atr_pos = g_atr_pos_base / atr_wv
atr_pos = self.atr_pos_base / atr_wv
# 最大仓位限制
atr_pos = ABuPositionBase.g_pos_max if atr_pos > ABuPositionBase.g_pos_max else atr_pos
atr_pos = self.pos_max if atr_pos > self.pos_max else atr_pos
# 结果是买入多少个单位(股,手,顿,合约)
return self.read_cash * atr_pos / self.bp * self.deposit_rate

def _init_self(self, **kwargs):
"""atr仓位控制管理类初始化设置"""
self.atr_base_price = kwargs.pop('atr_base_price', AbuAtrPosition.s_atr_base_price)
self.std_atr_threshold = kwargs.pop('std_atr_threshold', AbuAtrPosition.s_std_atr_threshold)
self.atr_pos_base = kwargs.pop('atr_pos_base', g_atr_pos_base)
40 changes: 17 additions & 23 deletions abupy/BetaBu/ABuKellyPosition.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
# -*- encoding:utf-8 -*-
"""
示例仓位管理:kelly仓位管理模块
"""
"""示例仓位管理:kelly仓位管理模块"""

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

from .ABuPositionBase import AbuPositionBase
from . import ABuPositionBase


class AbuKellyPosition(AbuPositionBase):
@@ -22,26 +19,23 @@ def fit_position(self, factor_object):
:param factor_object: ABuFactorBuyBases子类实例对象
:return:买入多少个单位(股,手,顿,合约)
"""

# 检测择时策略因子对象有没有设置设置胜率,期望收益,期望亏损,详情查阅ABuFactorBuyBase
if not hasattr(factor_object, 'win_rate'):
raise RuntimeError('AbuKellyPosition need factor_object has win_rate')
if not hasattr(factor_object, 'gains_mean'):
raise RuntimeError('AbuKellyPosition need factor_object has gains_mean')
if not hasattr(factor_object, 'losses_mean'):
raise RuntimeError('AbuKellyPosition need factor_object has losses_mean')

# 胜率
win_rate = factor_object.win_rate
# 败率
loss_rate = 1 - win_rate
# 平均获利期望
gains_mean = factor_object.gains_mean
# 平均亏损期望
losses_mean = factor_object.losses_mean
loss_rate = 1 - self.win_rate
# kelly计算出仓位比例
kelly_pos = win_rate - loss_rate / (gains_mean / losses_mean)
# 最大仓位限制
kelly_pos = ABuPositionBase.g_pos_max if kelly_pos > ABuPositionBase.g_pos_max else kelly_pos
kelly_pos = self.win_rate - loss_rate / (self.gains_mean / self.losses_mean)
# 最大仓位限制,依然受上层最大仓位控制限制,eg:如果kelly计算出全仓,依然会减少到75%,如修改需要修改最大仓位值
kelly_pos = self.pos_max if kelly_pos > self.pos_max else kelly_pos
# 结果是买入多少个单位(股,手,顿,合约)
return self.read_cash * kelly_pos / self.bp * self.deposit_rate

def _init_self(self, **kwargs):
"""kelly仓位控制管理类初始化设置"""

# 默认kelly仓位胜率0.50
self.win_rate = kwargs.pop('win_rate', 0.50)
# 默认平均获利期望0.10
self.gains_mean = kwargs.pop('gains_mean', 0.10)
# 默认平均亏损期望0.05
self.losses_mean = kwargs.pop('losses_mean', 0.05)

"""以默认的设置kelly根据计算0.5 - 0.5 / (0.10 / 0.05) 仓位将是0.25即25%"""
28 changes: 24 additions & 4 deletions abupy/BetaBu/ABuPositionBase.py
Original file line number Diff line number Diff line change
@@ -12,20 +12,28 @@
from ..CoreBu.ABuFixes import six
from ..MarketBu.ABuMarket import MarketMixin

"""每一笔交易最大仓位比例设置,外部可通过如:abupy.beta.position.g_pos_max = 0.5修改最大每一笔交易最大仓位比例"""
"""每一笔交易最大仓位比例设置,外部可通过如:abupy.beta.position.g_pos_max = 0.5修改最大每一笔交易最大仓位比例,默认75%"""
g_pos_max = 0.75
"""
保证净最小比例,默认1,即不使用融资,不会触发Margin Call
保证金最小比例,默认1,即不使用融资,不会触发Margin Call
在期货数据中有每种商品最少保证金比例,可使用设置
外部可通过如:abupy.beta.position.g_deposit_rate = 0.5
"""
g_deposit_rate = 1
"""
买入因子全局默认仓位管理类,默认None的情况下会使用AbuAtrPosition作为默认仓位管理类.
和卖出因子,选股因子不同,一个买入因子可以对应多个卖出因子,多个选股因子,但一个买入
因子只能对应一个仓位管理类,可以是全局仓位管理,也可以是针对买入因子的独有附属仓位管理
"""
g_default_pos_class = None


class AbuPositionBase(six.with_metaclass(ABCMeta, MarketMixin)):
"""仓位管理抽象基类"""

def __init__(self, kl_pd_buy, factor_name, symbol_name, bp, read_cash, deposit_rate):
def __init__(self, kl_pd_buy, factor_name, symbol_name, bp, read_cash, **kwargs):
"""
:param kl_pd_buy: 交易当日的交易数据
:param factor_name: 因子名称
@@ -39,7 +47,14 @@ def __init__(self, kl_pd_buy, factor_name, symbol_name, bp, read_cash, deposit_r
self.symbol_name = symbol_name
self.bp = bp
self.read_cash = read_cash
self.deposit_rate = deposit_rate

# 如果有全局最大仓位设置基类负责弹出
self.pos_max = kwargs.pop('pos_max', g_pos_max)
# 如果有全局保证金最小比例设置基类负责弹出
self.deposit_rate = kwargs.pop('deposit_rate', g_deposit_rate)

# 子类继续完成自有的构造
self._init_self(**kwargs)

def __str__(self):
"""打印对象显示:class name, factor_name, symbol_name, read_cash, deposit_rate"""
@@ -51,6 +66,11 @@ def __str__(self):

__repr__ = __str__

@abstractmethod
def _init_self(self, **kwargs):
"""子类仓位管理针对可扩展参数的初始化"""
pass

@abstractmethod
def fit_position(self, factor_object):
"""
46 changes: 32 additions & 14 deletions abupy/CoreBu/ABuEnv.py
100644 → 100755
Original file line number Diff line number Diff line change
@@ -118,6 +118,7 @@ def str_is_cn(a_str):
K_CN_RE.search(a_str)('abc哈哈') -> <_sre.SRE_Match object; span=(3, 5), match='哈哈'>
return True
"""

def to_unicode(text, encoding=None, errors='strict'):
"""
to_unicode原始位置: UtilBu.ABuStrUtil,为保持env为最初初始化不引入其它模块,这里临时拷贝使用
@@ -134,6 +135,7 @@ def to_unicode(text, encoding=None, errors='strict'):
cn_re = re.compile(u'[\u4e00-\u9fa5]+')
return cn_re.search(to_unicode(a_str)) is not None


root_drive = path.expanduser('~')
# root_drive = os.path.join(root_drive, u'测试')
# noinspection PyTypeChecker
@@ -169,9 +171,11 @@ def to_unicode(text, encoding=None, errors='strict'):
g_project_kl_df_data = path.join(g_project_data_dir, 'df_kl.h5')

_p_dir = os.path.abspath(os.path.join(os.path.dirname(os.path.realpath(__file__)), os.path.pardir))
"""使用书中相同的沙盒数据环境,RomDataBu/df_kl.h5中内置的金融时间序列文件"""
g_project_kl_df_data_example = os.path.join(_p_dir, 'RomDataBu/df_kl.h5')

# 不再使用hdf5做为默认,有windows用户的hdf5环境有问题
"""使用书中相同的沙盒数据环境,RomDataBu/csv内置的金融时间序列文件"""
# g_project_kl_df_data_example = os.path.join(_p_dir, 'RomDataBu/df_kl.h5')
g_project_kl_df_data_example = os.path.join(_p_dir, 'RomDataBu/csv')
# ******************** 数据目录 end ****************


@@ -340,26 +344,25 @@ class EMarketDataFetchMode(Enum):

def enable_example_env_ipython(show_log=True, check_cn=True):
"""
只为在ipython example 环境中运行与书中一样的数据,即读取RomDataBu/df_kl.h5下的数据
只为在ipython example 环境中运行与书中一样的数据,即读取RomDataBu/csv下的数据
初始内置在RomDataBu/df_kl.h5.zip下的数据只有zip压缩包,因为git上面的文件最好不要超过50m,
内置测试数据,包括美股,a股,期货,比特币,港股数据初始化在df_kl_ext.h5.zip中,通过解压zip
之后将测试数据为df_kl.h5
初始内置在RomDataBu/csv.zip下的数据只有zip压缩包,因为git上面的文件最好不要超过50m,
内置测试数据,包括美股,a股,期货,比特币,港股数据初始化在csv.zip中,通过解压zip
之后将测试数据为csv(老版本都是使用hdf5,但windows用户有些hdf5环境有问题)
show_log: 是否显示enable example env will only read RomDataBu/df_kl.h5
check_cn: 是否检测运行环境有中文路径
:return:
"""

if not os.path.exists(g_project_kl_df_data_example):
# 如果还没有进行解压,开始解压df_kl.h5.zip
data_example_zip = os.path.join(_p_dir, 'RomDataBu/df_kl.h5.zip')
# 如果还没有进行解压,开始解压csv.zip
data_example_zip = os.path.join(_p_dir, 'RomDataBu/csv.zip')
try:
from zipfile import ZipFile
zip_h5 = ZipFile(data_example_zip, 'r')
zip_csv = ZipFile(data_example_zip, 'r')
unzip_dir = os.path.join(_p_dir, 'RomDataBu/')
for h5 in zip_h5.namelist():
zip_h5.extract(h5, unzip_dir)
zip_h5.close()
for csv in zip_csv.namelist():
zip_csv.extract(csv, unzip_dir)
zip_csv.close()
except Exception as e:
# 解压测试数据zip失败,就不开启测试数据模式了
print('example env failed! e={}'.format(e))
@@ -380,7 +383,7 @@ def enable_example_env_ipython(show_log=True, check_cn=True):
except Exception as e:
logging.exception(e)
if show_log:
logging.info('enable example env will only read RomDataBu/df_kl.h5')
logging.info('enable example env will only read RomDataBu/csv')


def disable_example_env_ipython(show_log=True):
@@ -504,4 +507,19 @@ def init_logging():


init_logging()


# ******************** 日志 end ****************


def init_plot_set():
"""全局plot设置"""
import seaborn as sns
sns.set_context('notebook', rc={'figure.figsize': (14, 7)})
sns.set_style("darkgrid")

import matplotlib
# conda 5.0后需要添加单独matplotlib的figure设置否则pandas的plot size不生效
matplotlib.rcParams['figure.figsize'] = (14, 7)

init_plot_set()
2 changes: 1 addition & 1 deletion abupy/CoreBu/ABuParallel.py
Original file line number Diff line number Diff line change
@@ -86,7 +86,7 @@ def when_done(r):
self.n_jobs = ABuEnv.g_cpu_cnt

if self.n_jobs == 1:
# 如果只开一个进程,那么只在主进程里运行,方便pdb debug且与joblib运行方式保持一致
# 如果只开一个进程,那么只在主进程(或当前运行的子进程)里运行,方便pdb debug且与joblib运行方式保持一致
for jb in iterable:
result.append(jb[0](*jb[1], **jb[2]))
else:
Loading

0 comments on commit b5ec880

Please sign in to comment.