├── .gitattributes ├── .gitignore ├── LICENSE ├── abupy ├── AlphaBu │ ├── ABuAlpha.py │ ├── ABuPickBase.py │ ├── ABuPickStockExecute.py │ ├── ABuPickStockMaster.py │ ├── ABuPickStockWorker.py │ ├── ABuPickTimeExecute.py │ ├── ABuPickTimeMaster.py │ ├── ABuPickTimeWorker.py │ └── __init__.py ├── BetaBu │ ├── ABuAtrPosition.py │ ├── ABuBeta.py │ ├── ABuKellyPosition.py │ ├── ABuPositionBase.py │ ├── ABuPtPosition.py │ └── __init__.py ├── CheckBu │ ├── ABuChecker.py │ ├── ABuChecks.py │ ├── ABuFuncUtil.py │ ├── ABuProcessor.py │ └── __init__.py ├── CoreBu │ ├── ABu.py │ ├── ABuBase.py │ ├── ABuDeprecated.py │ ├── ABuEnv.py │ ├── ABuEnvProcess.py │ ├── ABuFixes.py │ ├── ABuParallel.py │ ├── ABuPdHelper.py │ ├── ABuStore.py │ └── __init__.py ├── CrawlBu │ ├── ABuXqApi.py │ ├── ABuXqConsts.py │ ├── ABuXqCrawl.py │ ├── ABuXqCrawlImp.py │ ├── ABuXqFile.py │ └── __init__.py ├── DLBu │ ├── ABuDL.py │ ├── ABuDLImgStd.py │ ├── ABuDLTVSplit.py │ ├── __init__.py │ ├── pb │ │ ├── deploy.prototxt │ │ ├── solver.prototxt │ │ └── train_val.prototxt │ └── sh │ │ ├── Lmdb.sh │ │ ├── Mean.sh │ │ └── Train.sh ├── ExtBu │ ├── __init__.py │ ├── empyrical │ │ ├── __init__.py │ │ ├── _version.py │ │ ├── stats.py │ │ └── utils.py │ ├── funcsigs.py │ ├── futures │ │ ├── __init__.py │ │ ├── _base.py │ │ ├── process.py │ │ └── thread.py │ ├── joblib │ │ ├── __init__.py │ │ ├── _compat.py │ │ ├── _memory_helpers.py │ │ ├── _multiprocessing_helpers.py │ │ ├── _parallel_backends.py │ │ ├── disk.py │ │ ├── format_stack.py │ │ ├── func_inspect.py │ │ ├── hashing.py │ │ ├── logger.py │ │ ├── memory.py │ │ ├── my_exceptions.py │ │ ├── numpy_pickle.py │ │ ├── numpy_pickle_compat.py │ │ ├── numpy_pickle_utils.py │ │ ├── parallel.py │ │ ├── pool.py │ │ └── testing.py │ ├── odict.py │ └── six.py ├── FactorBuyBu │ ├── ABuBuyFactorWrap.py │ ├── ABuFactorBuyBase.py │ ├── ABuFactorBuyBreak.py │ ├── ABuFactorBuyDM.py │ ├── ABuFactorBuyDemo.py │ ├── ABuFactorBuyTrend.py │ ├── ABuFactorBuyWD.py │ └── __init__.py ├── FactorSellBu │ ├── ABuFS.py │ ├── ABuFactorAtrNStop.py │ ├── ABuFactorCloseAtrNStop.py │ ├── ABuFactorPreAtrNStop.py │ ├── ABuFactorSellBase.py │ ├── ABuFactorSellBreak.py │ ├── ABuFactorSellDM.py │ ├── ABuFactorSellNDay.py │ └── __init__.py ├── IndicatorBu │ ├── ABuND.py │ ├── ABuNDAtr.py │ ├── ABuNDBase.py │ ├── ABuNDBoll.py │ ├── ABuNDMa.py │ ├── ABuNDMacd.py │ ├── ABuNDRsi.py │ └── __init__.py ├── MLBu │ ├── ABuML.py │ ├── ABuMLApi.py │ ├── ABuMLBinsCs.py │ ├── ABuMLCreater.py │ ├── ABuMLExecute.py │ ├── ABuMLGrid.py │ ├── ABuMLPd.py │ └── __init__.py ├── MarketBu │ ├── ABuDataBase.py │ ├── ABuDataCache.py │ ├── ABuDataCheck.py │ ├── ABuDataFeed.py │ ├── ABuDataParser.py │ ├── ABuDataSource.py │ ├── ABuHkUnit.py │ ├── ABuIndustries.py │ ├── ABuMarket.py │ ├── ABuMarketDrawing.py │ ├── ABuNetWork.py │ ├── ABuSymbol.py │ ├── ABuSymbolFutures.py │ ├── ABuSymbolPd.py │ ├── ABuSymbolStock.py │ └── __init__.py ├── MetricsBu │ ├── ABuCrossVal.py │ ├── ABuGridHelper.py │ ├── ABuGridSearch.py │ ├── ABuMetrics.py │ ├── ABuMetricsBase.py │ ├── ABuMetricsFutures.py │ ├── ABuMetricsScore.py │ ├── ABuMetricsTC.py │ └── __init__.py ├── PickStockBu │ ├── ABuPickRegressAngMinMax.py │ ├── ABuPickSimilarNTop.py │ ├── ABuPickStock.py │ ├── ABuPickStockBase.py │ ├── ABuPickStockDemo.py │ ├── ABuPickStockPriceMinMax.py │ └── __init__.py ├── RomDataBu │ ├── csv.zip │ ├── futures_cn.csv │ ├── futures_gb.csv │ ├── hk_unit.csv │ ├── hq_nav.txt │ ├── ml_test.csv │ ├── stock_code_CN.csv │ ├── stock_code_HK.csv │ ├── stock_code_US.csv │ ├── stock_code_cn.txt │ ├── stock_code_hk.txt │ ├── stock_code_us.txt │ └── symbols_db.db ├── SimilarBu │ ├── ABuCorrcoef.py │ ├── ABuSimilar.py │ ├── ABuSimilarCache.py │ ├── ABuSimilarDrawing.py │ └── __init__.py ├── SlippageBu │ ├── ABuSlippage.py │ ├── ABuSlippageBuyBase.py │ ├── ABuSlippageBuyMean.py │ ├── ABuSlippageSellBase.py │ ├── ABuSlippageSellMean.py │ └── __init__.py ├── TLineBu │ ├── ABuTL.py │ ├── ABuTLAtr.py │ ├── ABuTLExecute.py │ ├── ABuTLGolden.py │ ├── ABuTLJump.py │ ├── ABuTLSimilar.py │ ├── ABuTLVwap.py │ ├── ABuTLWave.py │ ├── ABuTLine.py │ └── __init__.py ├── TradeBu │ ├── ABuBenchmark.py │ ├── ABuCapital.py │ ├── ABuCommission.py │ ├── ABuKLManager.py │ ├── ABuMLFeature.py │ ├── ABuOrder.py │ ├── ABuTradeDrawer.py │ ├── ABuTradeExecute.py │ ├── ABuTradeProxy.py │ └── __init__.py ├── UmpBu │ ├── ABuUmp.py │ ├── ABuUmpBase.py │ ├── ABuUmpEdgeBase.py │ ├── ABuUmpEdgeDeg.py │ ├── ABuUmpEdgeFull.py │ ├── ABuUmpEdgeMul.py │ ├── ABuUmpEdgePrice.py │ ├── ABuUmpEdgeWave.py │ ├── ABuUmpMainBase.py │ ├── ABuUmpMainDeg.py │ ├── ABuUmpMainFull.py │ ├── ABuUmpMainJump.py │ ├── ABuUmpMainMul.py │ ├── ABuUmpMainPrice.py │ ├── ABuUmpMainWave.py │ ├── ABuUmpManager.py │ └── __init__.py ├── UtilBu │ ├── ABuDTUtil.py │ ├── ABuDateUtil.py │ ├── ABuDelegateUtil.py │ ├── ABuFileUtil.py │ ├── ABuKLUtil.py │ ├── ABuLazyUtil.py │ ├── ABuMacUtil.py │ ├── ABuMd5.py │ ├── ABuOsUtil.py │ ├── ABuPlatform.py │ ├── ABuProgress.py │ ├── ABuRegUtil.py │ ├── ABuScalerUtil.py │ ├── ABuStatsUtil.py │ ├── ABuStrUtil.py │ ├── ABuWinUtil.py │ └── __init__.py ├── WidgetBu │ ├── ABuWGBFBase.py │ ├── ABuWGBRun.py │ ├── ABuWGBRunBase.py │ ├── ABuWGBSymbol.py │ ├── ABuWGBase.py │ ├── ABuWGBuyFactor.py │ ├── ABuWGCrossVal.py │ ├── ABuWGDATool.py │ ├── ABuWGGridSearch.py │ ├── ABuWGPSBase.py │ ├── ABuWGPickStock.py │ ├── ABuWGPosBase.py │ ├── ABuWGPosition.py │ ├── ABuWGQuantTool.py │ ├── ABuWGSFBase.py │ ├── ABuWGSMTool.py │ ├── ABuWGSellFactor.py │ ├── ABuWGStockInfo.py │ ├── ABuWGTLTool.py │ ├── ABuWGToolBase.py │ ├── ABuWGUmp.py │ ├── ABuWGUpdate.py │ ├── ABuWGVerifyTool.py │ └── __init__.py └── __init__.py ├── abupy_lecture ├── 0-abupy量化环境部署(ABU量化使用文档).ipynb ├── 1-择时策略的开发(ABU量化使用文档).ipynb ├── 10-比特币莱特币的回测(ABU量化使用文档).ipynb ├── 11-期货市场的回测(ABU量化使用文档).ipynb ├── 12-机器学习与比特币示例(ABU量化使用文档).ipynb ├── 13-量化技术分析应用(ABU量化使用文档).ipynb ├── 14-量化相关性分析应用(ABU量化使用文档).ipynb ├── 15-量化交易和搜索引擎(ABU量化使用文档).ipynb ├── 16-UMP主裁交易决策(ABU量化使用文档).ipynb ├── 17-UMP边裁交易决策(ABU量化使用文档).ipynb ├── 18-自定义裁判决策交易(ABU量化使用文档).ipynb ├── 19-数据源(ABU量化使用文档).ipynb ├── 2-择时策略的优化(ABU量化使用文档).ipynb ├── 20-A股全市场回测(ABU量化使用文档).ipynb ├── 21-A股UMP决策(ABU量化使用文档).ipynb ├── 22-美股全市场回测(ABU量化使用文档).ipynb ├── 23-美股UMP决策(ABU量化使用文档).ipynb ├── 24-比特币vs黄金,莱特币vs白银(ABU量化使用文档).ipynb ├── 25-期货市场内外盘低频统计套利.ipynb ├── 26-星期几是这个股票的好日子.ipynb ├── 27-狗股选股策略与择时策略的配合.ipynb ├── 28-真 • 动态自适应双均线策略.ipynb ├── 29-多因子策略并行执行配合.ipynb ├── 3-滑点策略与交易手续费(ABU量化使用文档).ipynb ├── 30-趋势跟踪与均值回复的长短线搭配.ipynb ├── 31-资金仓位管理与买入策略的搭配.ipynb ├── 32-策略有效性的验证.ipynb ├── 4-多支股票择时回测与仓位管理(ABU量化使用文档).ipynb ├── 5-选股策略的开发(ABU量化使用文档).ipynb ├── 6-回测结果的度量(ABU量化使用文档).ipynb ├── 7-寻找策略最优参数和评分(ABU量化使用文档).ipynb ├── 8-A股市场的回测(ABU量化使用文档).ipynb ├── 9-港股市场的回测(ABU量化使用文档).ipynb ├── graphviz.png └── image │ ├── 1.1.png │ ├── 1.2.png │ ├── 1.3.png │ ├── 3.1.png │ ├── abu_logo.png │ ├── du_trend.png │ ├── f_trend.png │ ├── g_trend.png │ ├── gg.jpg │ ├── mmm.png │ ├── pig3.png │ ├── pos_trend.png │ ├── qrcode.jpg │ ├── run_ui.png │ ├── save_cv.png │ ├── st_mod.png │ ├── ump.png │ ├── ump_trade.png │ └── zsg.jpg ├── abupy_ui ├── gif │ ├── change_analyse.gif │ ├── channel_line.gif │ ├── golden_line.gif │ ├── jump_line.gif │ ├── loop_back.gif │ ├── regress_line.gif │ ├── rs_line.gif │ ├── sd_line.gif │ ├── similar_line.gif │ ├── stock_info.gif │ └── v_sense_line.gif ├── readme.md ├── run_cell.png ├── widget_base.py ├── widget_loop_back.py ├── widget_quant_tool.py ├── widget_stock_info.py ├── widget_update_ui.py ├── widget_verify_tool.py ├── 历史回测界面操作.ipynb ├── 参数最优交叉验证.ipynb ├── 数据下载界面操作.ipynb ├── 股票基本信息查询.ipynb └── 量化分析工具操作.ipynb ├── gen └── stock_day_change.npy ├── img ├── abu_logo.png ├── d2.png ├── d3.png ├── fl.png ├── head.png ├── img1.png ├── img10.png ├── img11.png ├── img12.png ├── img13.png ├── img14.png ├── img2.png ├── img3.png ├── img4.png ├── img5.png ├── img6.png ├── img7.png ├── img8.png ├── img9.png ├── qrcode.jpg └── quant_icon.png ├── ipython ├── readme.md ├── 第七章-量化系统——入门.ipynb ├── 第三章-量化工具——NumPy.ipynb ├── 第九章-量化系统——度量与优化.ipynb ├── 第二章-量化语言——Python.ipynb ├── 第五章-量化工具——可视化.ipynb ├── 第八章-量化系统——开发.ipynb ├── 第六章-量化工具——数学.ipynb ├── 第十一章-量化系统——机器学习•ABU.ipynb ├── 第十章-量化系统——机器学习•猪老三.ipynb ├── 第四章-量化工具——pandas.ipynb ├── 附录A-量化环境部署.ipynb ├── 附录B-量化相关性分析.ipynb └── 附录C-量化统计分析及指标应用.ipynb ├── python ├── abu_local_env.py ├── c10.py ├── c11.py ├── c2.py ├── c3.py ├── c4.py ├── c5.py ├── c6.py ├── c7.py ├── c8.py ├── c9.py ├── extA.py ├── extB.py ├── extC.py ├── graphviz.png ├── happy_life.py ├── readme.md ├── stock_days.py └── stock_dream_ml.py ├── readme-en.md ├── readme.md └── 界面操作视频教程 ├── 第26节星期几是这个股票的好日子界面操作视频.md └── 第一节界面操作视频教程.md /.gitattributes: -------------------------------------------------------------------------------- 1 | *.ipynb linguist-language=Python -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .ipynb_checkpoints* 2 | .idea 3 | .DS_Store 4 | logging.log 5 | p.sh 6 | *.pyc 7 | tmp 8 | test.py 9 | /abupy/RomDataBu/df_kl.h5 -------------------------------------------------------------------------------- /abupy/AlphaBu/ABuAlpha.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | # noinspection PyUnresolvedReferences 4 | from .ABuPickStockExecute import do_pick_stock_work 5 | # noinspection PyUnresolvedReferences 6 | from .ABuPickTimeExecute import do_symbols_with_same_factors, do_symbols_with_diff_factors 7 | # noinspection all 8 | from . import ABuPickTimeWorker as pick_time_worker 9 | -------------------------------------------------------------------------------- /abupy/AlphaBu/ABuPickBase.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | """ 3 | 择时与选股抽象基类 4 | """ 5 | 6 | from __future__ import absolute_import 7 | from __future__ import print_function 8 | from __future__ import division 9 | 10 | from abc import ABCMeta, abstractmethod 11 | 12 | from ..CoreBu.ABuFixes import six 13 | from ..CoreBu.ABuBase import AbuParamBase 14 | 15 | __author__ = '阿布' 16 | __weixin__ = 'abu_quant' 17 | 18 | 19 | class AbuPickTimeWorkBase(six.with_metaclass(ABCMeta, AbuParamBase)): 20 | """择时抽象基类""" 21 | 22 | @abstractmethod 23 | def fit(self, *args, **kwargs): 24 | """ 25 | fit在整个项目中的意义为开始对象最重要的工作, 26 | 对于择时对象即为开始择时操作,或者从字面理解 27 | 开始针对交易数据进行拟合择时操作 28 | """ 29 | pass 30 | 31 | @abstractmethod 32 | def init_sell_factors(self, *args, **kwargs): 33 | """ 34 | 初始化择时卖出因子 35 | """ 36 | pass 37 | 38 | @abstractmethod 39 | def init_buy_factors(self, *args, **kwargs): 40 | """ 41 | 初始化择时买入因子 42 | """ 43 | pass 44 | 45 | 46 | class AbuPickStockWorkBase(six.with_metaclass(ABCMeta, AbuParamBase)): 47 | """选股抽象基""" 48 | 49 | @abstractmethod 50 | def fit(self, *args, **kwargs): 51 | """ 52 | fit在整个项目中的意义为开始对象最重要的工作, 53 | 对于选股对象即为开始选股操作,或者从字面理解 54 | 开始针对交易数据进行拟合选股操作 55 | """ 56 | pass 57 | 58 | @abstractmethod 59 | def init_stock_pickers(self, *args, **kwargs): 60 | """ 61 | 初始化选股因子 62 | """ 63 | pass 64 | -------------------------------------------------------------------------------- /abupy/AlphaBu/ABuPickStockExecute.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | """ 3 | 包装选股worker进行,完善前后工作 4 | """ 5 | 6 | from __future__ import absolute_import 7 | from __future__ import print_function 8 | from __future__ import division 9 | 10 | from .ABuPickStockWorker import AbuPickStockWorker 11 | from ..CoreBu.ABuEnvProcess import add_process_env_sig 12 | from ..MarketBu.ABuMarket import split_k_market 13 | from ..TradeBu.ABuKLManager import AbuKLManager 14 | from ..CoreBu.ABuFixes import ThreadPoolExecutor 15 | 16 | __author__ = '阿布' 17 | __weixin__ = 'abu_quant' 18 | 19 | 20 | @add_process_env_sig 21 | def do_pick_stock_work(choice_symbols, benchmark, capital, stock_pickers): 22 | """ 23 | 包装AbuPickStockWorker进行选股 24 | :param choice_symbols: 初始备选交易对象序列 25 | :param benchmark: 交易基准对象,AbuBenchmark实例对象 26 | :param capital: 资金类AbuCapital实例化对象 27 | :param stock_pickers: 选股因子序列 28 | :return: 29 | """ 30 | kl_pd_manager = AbuKLManager(benchmark, capital) 31 | stock_pick = AbuPickStockWorker(capital, benchmark, kl_pd_manager, choice_symbols=choice_symbols, 32 | stock_pickers=stock_pickers) 33 | stock_pick.fit() 34 | return stock_pick.choice_symbols 35 | 36 | 37 | @add_process_env_sig 38 | def do_pick_stock_thread_work(choice_symbols, benchmark, capital, stock_pickers, n_thread): 39 | """包装AbuPickStockWorker启动线程进行选股""" 40 | result = [] 41 | 42 | def when_thread_done(r): 43 | result.extend(r.result()) 44 | 45 | with ThreadPoolExecutor(max_workers=n_thread) as pool: 46 | thread_symbols = split_k_market(n_thread, market_symbols=choice_symbols) 47 | for symbols in thread_symbols: 48 | future_result = pool.submit(do_pick_stock_work, symbols, benchmark, capital, stock_pickers) 49 | future_result.add_done_callback(when_thread_done) 50 | 51 | return result 52 | -------------------------------------------------------------------------------- /abupy/AlphaBu/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from .ABuPickBase import AbuPickTimeWorkBase, AbuPickStockWorkBase 4 | 5 | from .ABuPickStockMaster import AbuPickStockMaster 6 | from .ABuPickStockWorker import AbuPickStockWorker 7 | 8 | from .ABuPickTimeWorker import AbuPickTimeWorker 9 | from .ABuPickTimeMaster import AbuPickTimeMaster 10 | 11 | from . import ABuPickStockExecute 12 | from . import ABuPickTimeExecute 13 | # noinspection all 14 | from . import ABuAlpha as alpha 15 | 16 | __all__ = [ 17 | 'AbuPickTimeWorkBase', 18 | 'AbuPickStockWorkBase', 19 | 'AbuPickStockMaster', 20 | 'AbuPickStockWorker', 21 | 'AbuPickTimeWorker', 22 | 'AbuPickTimeMaster', 23 | 24 | 'ABuPickStockExecute', 25 | 'ABuPickTimeExecute', 26 | 'alpha' 27 | ] 28 | -------------------------------------------------------------------------------- /abupy/BetaBu/ABuAtrPosition.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | """ 3 | 示例仓位管理:atr仓位管理模块 4 | """ 5 | 6 | from __future__ import division 7 | from __future__ import absolute_import 8 | from __future__ import print_function 9 | 10 | from .ABuPositionBase import AbuPositionBase 11 | 12 | __author__ = '阿布' 13 | __weixin__ = 'abu_quant' 14 | 15 | """ 16 | 默认0.1即10% 外部可通过如:abupy.beta.atr.g_atr_pos_base = 0.01修改仓位基础配比 17 | 需要注意外部其它自定义仓位管理类不要随意使用模块全局变量,AbuAtrPosition特殊因为注册 18 | 在ABuEnvProcess中在多进程启动时拷贝了模块全局设置内存 19 | """ 20 | g_atr_pos_base = 0.1 21 | 22 | 23 | class AbuAtrPosition(AbuPositionBase): 24 | """示例atr仓位管理类""" 25 | 26 | s_atr_base_price = 15 # best fit wide: 12-20 27 | s_std_atr_threshold = 0.5 # best fit wide: 0.3-0.65 28 | 29 | def fit_position(self, factor_object): 30 | """ 31 | fit_position计算的结果是买入多少个单位(股,手,顿,合约) 32 | 计算:(常数价格 / 买入价格)* 当天交易日atr21 33 | :param factor_object: ABuFactorBuyBases实例对象 34 | :return: 买入多少个单位(股,手,顿,合约) 35 | """ 36 | std_atr = (self.atr_base_price / self.bp) * self.kl_pd_buy['atr21'] 37 | 38 | """ 39 | 对atr 进行限制 避免由于股价波动过小,导致 40 | atr小,产生大量买单,实际上针对这种波动异常(过小,过大)的股票 41 | 需要有其它的筛选过滤策略, 选股的时候取0.5,这样最大取两倍g_atr_pos_base 42 | """ 43 | atr_wv = self.std_atr_threshold if std_atr < self.std_atr_threshold else std_atr 44 | # 计算出仓位比例 45 | atr_pos = self.atr_pos_base / atr_wv 46 | # 最大仓位限制 47 | atr_pos = self.pos_max if atr_pos > self.pos_max else atr_pos 48 | # 结果是买入多少个单位(股,手,顿,合约) 49 | return self.read_cash * atr_pos / self.bp * self.deposit_rate 50 | 51 | def _init_self(self, **kwargs): 52 | """atr仓位控制管理类初始化设置""" 53 | self.atr_base_price = kwargs.pop('atr_base_price', AbuAtrPosition.s_atr_base_price) 54 | self.std_atr_threshold = kwargs.pop('std_atr_threshold', AbuAtrPosition.s_std_atr_threshold) 55 | self.atr_pos_base = kwargs.pop('atr_pos_base', g_atr_pos_base) 56 | -------------------------------------------------------------------------------- /abupy/BetaBu/ABuBeta.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | from __future__ import absolute_import 3 | 4 | # noinspection all 5 | from . import ABuPositionBase as position 6 | # noinspection all 7 | from . import ABuAtrPosition as atr 8 | # noinspection all 9 | from . import ABuKellyPosition as kelly 10 | -------------------------------------------------------------------------------- /abupy/BetaBu/ABuKellyPosition.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | """示例仓位管理:kelly仓位管理模块""" 3 | 4 | from __future__ import division 5 | from __future__ import absolute_import 6 | from __future__ import print_function 7 | 8 | from .ABuPositionBase import AbuPositionBase 9 | 10 | 11 | class AbuKellyPosition(AbuPositionBase): 12 | """示例kelly仓位管理类""" 13 | 14 | def fit_position(self, factor_object): 15 | """ 16 | 通过kelly公司计算仓位, fit_position计算的结果是买入多少个单位(股,手,顿,合约) 17 | :param factor_object: ABuFactorBuyBases子类实例对象 18 | :return:买入多少个单位(股,手,顿,合约) 19 | """ 20 | # 败率 21 | loss_rate = 1 - self.win_rate 22 | # kelly计算出仓位比例 23 | kelly_pos = self.win_rate - loss_rate / (self.gains_mean / self.losses_mean) 24 | # 最大仓位限制,依然受上层最大仓位控制限制,eg:如果kelly计算出全仓,依然会减少到75%,如修改需要修改最大仓位值 25 | kelly_pos = self.pos_max if kelly_pos > self.pos_max else kelly_pos 26 | # 结果是买入多少个单位(股,手,顿,合约) 27 | return self.read_cash * kelly_pos / self.bp * self.deposit_rate 28 | 29 | def _init_self(self, **kwargs): 30 | """kelly仓位控制管理类初始化设置""" 31 | 32 | # 默认kelly仓位胜率0.50 33 | self.win_rate = kwargs.pop('win_rate', 0.50) 34 | # 默认平均获利期望0.10 35 | self.gains_mean = kwargs.pop('gains_mean', 0.10) 36 | # 默认平均亏损期望0.05 37 | self.losses_mean = kwargs.pop('losses_mean', 0.05) 38 | 39 | """以默认的设置kelly根据计算0.5 - 0.5 / (0.10 / 0.05) 仓位将是0.25即25%""" 40 | -------------------------------------------------------------------------------- /abupy/BetaBu/ABuPositionBase.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | """ 3 | 风险控制仓位管理基础 4 | """ 5 | 6 | from __future__ import absolute_import 7 | from __future__ import division 8 | from __future__ import print_function 9 | 10 | from abc import ABCMeta, abstractmethod 11 | 12 | from ..CoreBu.ABuFixes import six 13 | from ..MarketBu.ABuMarket import MarketMixin 14 | 15 | """每一笔交易最大仓位比例设置,外部可通过如:abupy.beta.position.g_pos_max = 0.5修改最大每一笔交易最大仓位比例,默认75%""" 16 | g_pos_max = 0.75 17 | """ 18 | 保证金最小比例,默认1,即不使用融资,不会触发Margin Call 19 | 在期货数据中有每种商品最少保证金比例,可使用设置 20 | 外部可通过如:abupy.beta.position.g_deposit_rate = 0.5 21 | """ 22 | g_deposit_rate = 1 23 | """ 24 | 买入因子全局默认仓位管理类,默认None的情况下会使用AbuAtrPosition作为默认仓位管理类. 25 | 26 | 和卖出因子,选股因子不同,一个买入因子可以对应多个卖出因子,多个选股因子,但一个买入 27 | 因子只能对应一个仓位管理类,可以是全局仓位管理,也可以是针对买入因子的独有附属仓位管理 28 | 类 29 | """ 30 | g_default_pos_class = None 31 | 32 | 33 | class AbuPositionBase(six.with_metaclass(ABCMeta, MarketMixin)): 34 | """仓位管理抽象基类""" 35 | 36 | def __init__(self, kl_pd_buy, factor_name, symbol_name, bp, read_cash, **kwargs): 37 | """ 38 | :param kl_pd_buy: 交易当日的交易数据 39 | :param factor_name: 因子名称 40 | :param symbol_name: symbol代码 41 | :param bp: 买入价格 42 | :param read_cash: 初始资金 43 | :param deposit_rate: 保证金比例 44 | """ 45 | self.kl_pd_buy = kl_pd_buy 46 | self.factor_name = factor_name 47 | self.symbol_name = symbol_name 48 | self.bp = bp 49 | self.read_cash = read_cash 50 | 51 | # 如果有全局最大仓位设置基类负责弹出 52 | self.pos_max = kwargs.pop('pos_max', g_pos_max) 53 | # 如果有全局保证金最小比例设置基类负责弹出 54 | self.deposit_rate = kwargs.pop('deposit_rate', g_deposit_rate) 55 | 56 | # 子类继续完成自有的构造 57 | self._init_self(**kwargs) 58 | 59 | def __str__(self): 60 | """打印对象显示:class name, factor_name, symbol_name, read_cash, deposit_rate""" 61 | return '{}: factor_name:{}, symbol_name:{}, read_cash:{}, deposit_rate:{}'.format(self.__class__.__name__, 62 | self.factor_name, 63 | self.symbol_name, 64 | self.read_cash, 65 | self.deposit_rate) 66 | 67 | __repr__ = __str__ 68 | 69 | @abstractmethod 70 | def _init_self(self, **kwargs): 71 | """子类仓位管理针对可扩展参数的初始化""" 72 | pass 73 | 74 | @abstractmethod 75 | def fit_position(self, factor_object): 76 | """ 77 | fit_position计算的结果是买入多少个单位(股,手,顿,合约)具体计算子类实现 78 | :param factor_object: ABuFactorBuyBases实例对象 79 | :return:买入多少个单位(股,手,顿,合约) 80 | """ 81 | pass 82 | -------------------------------------------------------------------------------- /abupy/BetaBu/ABuPtPosition.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | """示例仓位管理:示例价格位置仓位模块""" 3 | 4 | from __future__ import division 5 | from __future__ import absolute_import 6 | from __future__ import print_function 7 | 8 | from scipy import stats 9 | 10 | from .ABuPositionBase import AbuPositionBase 11 | 12 | 13 | class AbuPtPosition(AbuPositionBase): 14 | """ 15 | 示例价格位置仓位管理类: 16 | 17 | 根据买入价格在之前一段时间的价格位置来决策仓位大小 18 | 19 | 假设过去一段时间的价格为[10, 9, 8, 7, 6, 5, 4, 3, 2, 1] 20 | 如果当前买入价格为2元:则买入仓位配比很高(认为均值回复有很大向上空间) 21 | 如果当前买入价格为9元:则买入仓位配比很低(认为均值回复向上空间比较小) 22 | """ 23 | 24 | def fit_position(self, factor_object): 25 | """ 26 | 针对均值回复类型策略的仓位管理: 27 | 根据当前买入价格在过去一段金融序列中的价格rank位置来决定仓位 28 | fit_position计算的结果是买入多少个单位(股,手,顿,合约) 29 | :param factor_object: ABuFactorBuyBases子类实例对象 30 | :return:买入多少个单位(股,手,顿,合约) 31 | """ 32 | 33 | # self.kl_pd_buy为买入当天的数据,获取之前的past_day_cnt天数据 34 | last_kl = factor_object.past_today_kl(self.kl_pd_buy, self.past_day_cnt) 35 | if last_kl is None or last_kl.empty: 36 | precent_pos = self.pos_base 37 | else: 38 | # 使用percentileofscore计算买入价格在过去的past_day_cnt天的价格位置 39 | precent_pos = stats.percentileofscore(last_kl.close, self.bp) 40 | precent_pos = (1 + (self.mid_precent - precent_pos) / 100) * self.pos_base 41 | # 最大仓位限制,依然受上层最大仓位控制限制,eg:如果算出全仓,依然会减少到75%,如修改需要修改最大仓位值 42 | precent_pos = self.pos_max if precent_pos > self.pos_max else precent_pos 43 | # 结果是买入多少个单位(股,手,顿,合约) 44 | return self.read_cash * precent_pos / self.bp * self.deposit_rate 45 | 46 | def _init_self(self, **kwargs): 47 | """价格位置仓位控制管理类初始化设置""" 48 | # 默认平均仓位比例0.10,即10% 49 | self.pos_base = kwargs.pop('pos_base', 0.10) 50 | # 默认获取之前金融时间序列的长短数量 51 | self.past_day_cnt = kwargs.pop('past_day_cnt', 20) 52 | # 默认的比例中值,一般不需要设置 53 | self.mid_precent = kwargs.pop('mid_precent', 50.0) 54 | -------------------------------------------------------------------------------- /abupy/BetaBu/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from .ABuPositionBase import AbuPositionBase 4 | from .ABuAtrPosition import AbuAtrPosition 5 | from .ABuKellyPosition import AbuKellyPosition 6 | from .ABuPtPosition import AbuPtPosition 7 | # noinspection all 8 | from . import ABuBeta as beta 9 | 10 | __all__ = [ 11 | 'AbuPositionBase', 12 | 'AbuAtrPosition', 13 | 'AbuKellyPosition', 14 | 'AbuPtPosition', 15 | 'beta' 16 | ] 17 | -------------------------------------------------------------------------------- /abupy/CheckBu/ABuChecks.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | """ 3 | 检查范围的函数 4 | """ 5 | 6 | from __future__ import print_function 7 | from __future__ import absolute_import 8 | from __future__ import division 9 | 10 | import numpy as np 11 | from abc import ABCMeta 12 | 13 | from ..CoreBu.ABuFixes import six 14 | 15 | __author__ = '夜猫' 16 | __weixin__ = 'abu_quant' 17 | 18 | 19 | class CheckError(six.with_metaclass(ABCMeta, TypeError)): 20 | """Check失败的Error类型""" 21 | pass 22 | 23 | 24 | def bound_check(bound): 25 | """ 26 | 制作检查数值范围的check_fail函数 27 | """ 28 | (min_val, max_val) = bound 29 | # 转换None到inf 30 | min_val = -np.inf if min_val is None else min_val 31 | max_val = np.inf if max_val is None else max_val 32 | # 准备错误message 33 | error_msg = "function expected a return value inclusively between %s and %s" % (min_val, max_val) 34 | 35 | def _check(value): 36 | """范围检查逻辑""" 37 | return not (min_val <= value <= max_val) 38 | 39 | def _bound_check(val): 40 | """ 41 | 检查数值范围的函数;检查失败raise CheckError 42 | """ 43 | if _check(val): 44 | raise CheckError(error_msg) 45 | else: 46 | return val 47 | 48 | return _bound_check 49 | 50 | 51 | def bound_valid_and_check(bound): 52 | """ 53 | 检查bound的输入参数格式;失败raise TypeError 54 | 传入参数形式应为`` (min_value, max_value)``. 55 | """ 56 | 57 | def valid_bound(t): 58 | # 检查bound传入参数格式 59 | return ( 60 | isinstance(t, tuple) 61 | and len(t) == 2 62 | and t != (None, None) 63 | ) 64 | 65 | if not valid_bound(bound): 66 | # 参数格式错误 67 | raise TypeError( 68 | "function expected a tuple of bounds," 69 | "but got {} instead.".format(bound) 70 | ) 71 | return bound_check(bound) 72 | 73 | 74 | def subset_check(subset): 75 | """ 76 | 制作检查是否子集的check函数 77 | """ 78 | 79 | def _check(arg_val): 80 | """ 81 | 检查数值是否子集的check函数;检查失败raise CheckError 82 | """ 83 | if subset is not None and arg_val not in set(subset): 84 | raise CheckError( 85 | 'Value {} is not the subset of {}'.format(arg_val, str(subset)) 86 | ) 87 | return arg_val 88 | 89 | return _check 90 | 91 | 92 | def type_check(arg_ty): 93 | """ 94 | 制作检查数值类型的check函数 95 | """ 96 | 97 | def _check(arg_val): 98 | """ 99 | 检查数值类型的check函数;检查失败raise CheckError 100 | """ 101 | if arg_ty and not isinstance(arg_val, arg_ty): 102 | raise CheckError( 103 | 'Value {} is not {}'.format(arg_val, arg_ty) 104 | ) 105 | return arg_val 106 | 107 | return _check 108 | -------------------------------------------------------------------------------- /abupy/CheckBu/ABuFuncUtil.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | """ 3 | 函数对象的工具类 4 | """ 5 | 6 | from __future__ import print_function 7 | from __future__ import absolute_import 8 | from __future__ import division 9 | 10 | from collections import OrderedDict 11 | from abc import ABCMeta 12 | 13 | from ..CoreBu.ABuFixes import six 14 | 15 | try: 16 | from inspect import getfullargspec as getargspec 17 | except ImportError: 18 | 19 | from inspect import getargspec 20 | 21 | __author__ = '夜猫' 22 | __weixin__ = 'abu_quant' 23 | 24 | 25 | class ArgNoDefault(six.with_metaclass(ABCMeta, TypeError)): 26 | """没有默认值的参数对象""" 27 | pass 28 | 29 | 30 | def get_func_name(func): 31 | """ 32 | 获取函数名称 33 | :param func: 传入函数 34 | :return: 35 | """ 36 | try: 37 | func_name = str(func.__name__) + '()' 38 | except AttributeError: 39 | func_name = str(func) 40 | return func_name 41 | 42 | 43 | def get_arg_defaults(func): 44 | """ 45 | 获取函数默认值字典;没有默认值时对应NoDefaultArg对象 46 | :param func: 传入函数 47 | :return: 函数参数名:默认值 48 | """ 49 | # 解包函数参数及默认值 50 | argspec = getargspec(func) 51 | spec_args = argspec.args if argspec.args else [] 52 | defaults = argspec.defaults if argspec.defaults else () 53 | # 拼装默认值dict 54 | no_defaults = (ArgNoDefault(),) * (len(spec_args) - len(defaults)) 55 | args_defaults = dict(zip(spec_args, no_defaults + defaults)) 56 | return args_defaults 57 | 58 | 59 | def check_bind(func, *args, **kwargs): 60 | """ 61 | 检查要bind的对象和原函数func的参数是否对齐;对齐失败,raise TypeError 62 | :param func: 原函数 63 | :param args: 要bind的tuple对象 64 | :param kwargs: 要bind的dict对象 65 | :return: 66 | """ 67 | argspec = getargspec(func) 68 | spec_args = argspec.args if argspec.args else [] 69 | # 检查 kwargs 中是否有不存在的参数名 70 | bad_names = set(kwargs.keys()) - set(spec_args) 71 | if bad_names: 72 | raise TypeError( 73 | "Got unknown arguments: {}".format(str(bad_names)) 74 | ) 75 | # 检查args的参数是否过长 76 | l_arg_len = len(args) 77 | if len(spec_args) < l_arg_len + len(kwargs): 78 | raise TypeError( 79 | "Function with {} arguments, but got {} arguments to bind".format(len(spec_args), 80 | l_arg_len + len(kwargs)) 81 | ) 82 | # 检查 kwargs 中是否和 args的参数冲突 83 | arg_inds = OrderedDict(zip(spec_args, range(len(spec_args)))) 84 | for k, v in six.iteritems(kwargs): 85 | if l_arg_len > arg_inds[k]: 86 | raise TypeError( 87 | "dict argument crash on tuple argument: {}".format(str(k)) 88 | ) 89 | 90 | 91 | def bind_partial(func, *args, **kwargs): 92 | """ 93 | 绑定func的参数和对应的参数对象 94 | :param func: 原函数 95 | :param args: 要bind的tuple对象 96 | :param kwargs: 要bind的dict对象 97 | :return: 绑定后的字典 98 | """ 99 | # 解包函数参数 100 | argspec = getargspec(func) 101 | spec_args = argspec.args if argspec.args else [] 102 | 103 | # 拼装函数参数和对应的参数对象 104 | bind_dict = OrderedDict(zip(spec_args, [None] * len(spec_args))) 105 | for k, v in six.iteritems(kwargs): 106 | bind_dict[k] = v 107 | for k, v in zip(six.iterkeys(bind_dict), args): 108 | bind_dict[k] = v 109 | 110 | return bind_dict 111 | -------------------------------------------------------------------------------- /abupy/CheckBu/ABuProcessor.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | """ 3 | 预处理函数参数或返回值 4 | """ 5 | 6 | from __future__ import print_function 7 | from __future__ import absolute_import 8 | from __future__ import division 9 | 10 | from functools import wraps 11 | 12 | from ..CoreBu.ABuFixes import zip 13 | from ..CheckBu.ABuFuncUtil import * 14 | 15 | try: 16 | from ..ExtBu.six.moves import zip_longest 17 | except ImportError: 18 | from six.moves import zip_longest 19 | 20 | __author__ = '夜猫' 21 | __weixin__ = 'abu_quant' 22 | 23 | 24 | def arg_process(*arg_funcs, **kwarg_funcs): 25 | """ 26 | 【装饰器】 27 | 将funcs函数作用在原函数的参数上;func函数只包括一个参数: return_val. 28 | :param arg_funcs: func函数tuple。 29 | :param kwarg_funcs: func函数dict 30 | :return: 31 | """ 32 | 33 | def _decorator(func): 34 | # 检查待bind参数 35 | check_bind(func, *arg_funcs, **kwarg_funcs) 36 | # 提取funcs字典 37 | funcs = bind_partial(func, *arg_funcs, **kwarg_funcs) 38 | 39 | @wraps(func) 40 | def wrapper(*args, **kwargs): 41 | # 拼装经过函数处理后的新参数 42 | args_new = [f(arg) if f else arg for arg, f in zip(args, six.itervalues(funcs))] 43 | kwargs_new = {k: funcs[k](arg) if k in funcs and funcs[k] else arg 44 | for k, arg in six.iteritems(kwargs)} 45 | # 调用函数 46 | return func(*args_new, **kwargs_new) 47 | 48 | return wrapper 49 | 50 | return _decorator 51 | 52 | 53 | def return_process(*funcs, **_unused): 54 | """ 55 | 【装饰器】 56 | 将funcs函数作用在被装饰的函数的返回值上 57 | :param funcs: 一个或者多个处理对应参数的func函数,多个func函数时需要和返回值数量对齐;func函数只包括一个参数: return_val 58 | :param _unused: 用来屏蔽dict参数 59 | :return: 返回被funcs函数处理过的函数返回值 60 | """ 61 | # 屏蔽dict参数 62 | if _unused: 63 | raise TypeError("return_process() doesn't accept dict processors") 64 | 65 | def _decorator(f): 66 | def wrapper(*args, **kw): 67 | # 拿到返回值 68 | return_vals = f(*args, **kw) 69 | # 用函数处理返回值 70 | return _apply_funcs(return_vals, funcs) 71 | 72 | return wrapper 73 | 74 | return _decorator 75 | 76 | 77 | def _apply_funcs(return_vals, funcs): 78 | """ 79 | 将func函数作用在被装饰的函数的返回值上 80 | """ 81 | # 检查iterable 82 | if not isinstance(return_vals, tuple): 83 | return_vals = (return_vals,) 84 | try: 85 | iter(funcs) 86 | except TypeError: 87 | funcs = (funcs,) if funcs else () 88 | 89 | # 检查函数 90 | if not funcs: 91 | return return_vals 92 | 93 | # 函数和返回值不对齐 94 | if 1 < len(return_vals) < len(funcs): 95 | raise TypeError( 96 | "In _apply_funcs(), len(funcs) == {} more than len(return_vals) == {}".format( 97 | len(funcs), len(return_vals) 98 | ) 99 | ) 100 | # 函数多于返回值 101 | if 1 == len(return_vals) < len(funcs): 102 | raise TypeError( 103 | "In _apply_funcs(), only 1 return value with len(processors) == {}".format(len(funcs), 104 | len(return_vals)) 105 | ) 106 | 107 | # 将函数作用在返回值上 108 | return tuple([f(v) if f else v for v, f in zip_longest(return_vals, funcs)]) 109 | -------------------------------------------------------------------------------- /abupy/CheckBu/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from .ABuProcessor import arg_process, return_process 4 | from .ABuChecker import FuncChecker, ArgChecker, ReturnChecker 5 | 6 | __all__ = [ 7 | 'arg_process', 8 | 'return_process', 9 | 'FuncChecker', 10 | 'ArgChecker', 11 | 'ReturnChecker', 12 | ] 13 | -------------------------------------------------------------------------------- /abupy/CoreBu/ABuDeprecated.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | """ 3 | Deprecated警告模块 4 | """ 5 | 6 | import warnings 7 | 8 | from ..CoreBu.ABuFixes import six 9 | 10 | 11 | class AbuDeprecated(object): 12 | """支持装饰类或者方法,在使用类或者方法时警告Deprecated信息""" 13 | 14 | def __init__(self, tip_info=''): 15 | # 用户自定义警告信息tip_info 16 | self.tip_info = tip_info 17 | 18 | def __call__(self, obj): 19 | if isinstance(obj, six.class_types): 20 | # 针对类装饰 21 | return self._decorate_class(obj) 22 | else: 23 | # 针对方法装饰 24 | return self._decorate_fun(obj) 25 | 26 | def _decorate_class(self, cls): 27 | """实现类装饰警告Deprecated信息""" 28 | 29 | msg = "class {} is deprecated".format(cls.__name__) 30 | if self.tip_info: 31 | msg += "; {}".format(self.tip_info) 32 | # 取出原始init 33 | init = cls.__init__ 34 | 35 | def wrapped(*args, **kwargs): 36 | warnings.warn(msg, category=DeprecationWarning) 37 | return init(*args, **kwargs) 38 | 39 | cls.__init__ = wrapped 40 | 41 | wrapped.__name__ = '__init__' 42 | wrapped.__doc__ = self._update_doc(init.__doc__) 43 | # init成为deprecated_original,必须要使用这个属性名字,在其它地方,如AbuParamBase会寻找原始方法找它 44 | wrapped.deprecated_original = init 45 | 46 | return cls 47 | 48 | def _decorate_fun(self, fun): 49 | """实现方法装饰警告Deprecated信息""" 50 | 51 | msg = "func {} is deprecated".format(fun.__name__) 52 | if self.tip_info: 53 | msg += "; {}".format(self.tip_info) 54 | 55 | def wrapped(*args, **kwargs): 56 | warnings.warn(msg, category=DeprecationWarning) 57 | return fun(*args, **kwargs) 58 | 59 | # 更新func及文档信息 60 | wrapped.__name__ = fun.__name__ 61 | wrapped.__dict__ = fun.__dict__ 62 | wrapped.__doc__ = self._update_doc(fun.__doc__) 63 | 64 | return wrapped 65 | 66 | def _update_doc(self, func_doc): 67 | """更新文档信息,把原来的文档信息进行合并格式化, 即第一行为deprecated_doc(Deprecated: tip_info),下一行为原始func_doc""" 68 | deprecated_doc = "Deprecated" 69 | if self.tip_info: 70 | """如果有tip format tip""" 71 | deprecated_doc = "{}: {}".format(deprecated_doc, self.tip_info) 72 | if func_doc: 73 | # 把原来的文档信息进行合并格式化, 即第一行为deprecated_doc,下一行为原始func_doc 74 | func_doc = "{}\n{}".format(deprecated_doc, func_doc) 75 | return func_doc 76 | -------------------------------------------------------------------------------- /abupy/CoreBu/__init__.py: -------------------------------------------------------------------------------- 1 | # IN ABu LIST __all__ 2 | from __future__ import absolute_import 3 | 4 | from .ABuFixes import * 5 | from .ABuPdHelper import * 6 | from . import ABuEnv as env 7 | from . import ABu as abu 8 | from .ABuEnv import EMarketSourceType, EMarketTargetType, EMarketSubType, \ 9 | EMarketDataSplitMode, EMarketDataFetchMode, EDataCacheType 10 | from .ABuBase import AbuParamBase, FreezeAttrMixin, PickleStateMixin 11 | from .ABuParallel import Parallel, delayed 12 | from .ABuStore import AbuResultTuple, EStoreAbu 13 | 14 | __all__ = [ 15 | 'abu', 16 | 'AbuResultTuple', 17 | 'EStoreAbu', 18 | 'env', 19 | 'AbuParamBase', 20 | 'FreezeAttrMixin', 21 | 'PickleStateMixin', 22 | 'Parallel', 23 | 'delayed', 24 | 'EMarketSourceType', 25 | 'EMarketTargetType', 26 | 'EMarketSubType', 27 | 'EMarketDataSplitMode', 28 | 'EMarketDataFetchMode', 29 | 'EDataCacheType', 30 | 31 | 'train_test_split', 32 | 'KFold', 33 | 'learning_curve', 34 | 'cross_val_score', 35 | 'GridSearchCV', 36 | 37 | 'signature', 38 | 'Parameter', 39 | 40 | 'ThreadPoolExecutor', 41 | 'six', 42 | 'zip', 43 | 'xrange', 44 | 'range', 45 | 'reduce', 46 | 'map', 47 | 'filter', 48 | 'pickle', 49 | 'Pickler', 50 | 'Unpickler', 51 | 'partial', 52 | 53 | 'pd_rolling_mean', 54 | 'pd_rolling_std', 55 | 'pd_rolling_var', 56 | 'pd_rolling_median', 57 | 'pd_rolling_max', 58 | 'pd_rolling_min', 59 | 'pd_rolling_corr', 60 | 'pd_rolling_cov', 61 | 'pd_rolling_sum', 62 | 'pd_rolling_kurt', 63 | 'pd_rolling_skew', 64 | 65 | 'pd_ewm_mean', 66 | 'pd_ewm_corr', 67 | 'pd_ewm_std', 68 | 'pd_ewm_cov', 69 | 'pd_ewm_var', 70 | 71 | 'pd_expanding_mean', 72 | 'pd_expanding_std', 73 | 'pd_expanding_var', 74 | 'pd_expanding_median', 75 | 'pd_expanding_max', 76 | 'pd_expanding_min', 77 | 'pd_expanding_corr', 78 | 'pd_expanding_cov', 79 | 'pd_expanding_sum', 80 | 'pd_expanding_kurt', 81 | 'pd_expanding_skew', 82 | 83 | 'pd_resample' 84 | ] 85 | -------------------------------------------------------------------------------- /abupy/CrawlBu/ABuXqApi.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | from __future__ import print_function 3 | from __future__ import absolute_import 4 | from __future__ import division 5 | 6 | import time 7 | 8 | from ..CoreBu import ABuFixes 9 | 10 | __author__ = '小青蛙' 11 | __weixin__ = 'abu_quant' 12 | 13 | BASE_XQ_URL = 'https://xueqiu.com' 14 | 15 | BASE_XQ_HQ_URL = BASE_XQ_URL + '/hq' 16 | 17 | BASE_XQ_STOCK_INFO = BASE_XQ_URL + '/S/' 18 | 19 | BASE_XQ_HQ_EXCHANGE_URL = BASE_XQ_HQ_URL + '#exchange={}' 20 | 21 | CN_INDUSTRY_LIST = 'https://xueqiu.com/industry/quote_order.json?' \ 22 | 'size=100&order=asc&orderBy=code&exchange=CN&' 23 | HK_INDUSTRY_LIST = 'https://xueqiu.com/stock/cata/stocklist.json?' \ 24 | 'size=100&order=asc&orderby=code&exchange=HK&' 25 | US_INDUSTRY_LIST = 'https://xueqiu.com/stock/cata/stocklist.json?' \ 26 | 'size=100&order=asc&orderby=code&exchange=US&' 27 | 28 | CN_STOCK_LIST = 'https://xueqiu.com/stock/cata/stocklist.json?' \ 29 | 'size=100&order=asc&orderby=code&type=11%2C12&' 30 | HK_STOCK_LIST = 'https://xueqiu.com/stock/cata/stocklist.json?' \ 31 | 'size=100&order=asc&orderby=code&type=30%2C31&' 32 | US_STOCK_LIST = 'https://xueqiu.com/stock/cata/stocklist.json?' \ 33 | 'size=100&order=asc&orderby=code&type=0%2C1%2C2%2C3&isdelay=1&' 34 | 35 | LOGIN_URL = 'https://xueqiu.com/user/login' 36 | 37 | # 雪球url中type值 38 | TYPE_INFO = { 39 | 0: 'us_stock', # 美股(不包含中国区) 40 | 1: 'us_a_stock_NASDAQ', # 在拉斯达克上市的中国股票 41 | 2: 'us_a_stock_NYSE', # 在纽交所上市的中国股票 42 | 3: 'us_index', # 美国指数 43 | 11: 'a_stock', # A股 44 | 12: 'a_index', # A股指数 45 | 30: 'hk_stock', # 港股 46 | 31: 'hk_index', # 港股指数 47 | } 48 | 49 | 50 | class IndustryUrl(object): 51 | def __init__(self, market, **kwargs): 52 | self.market = market 53 | self.kwargs = kwargs 54 | self._base_url = None 55 | self.init_base_url() 56 | 57 | def init_base_url(self): 58 | if 'CN' == self.market: 59 | self._base_url = CN_INDUSTRY_LIST 60 | elif 'HK' == self.market: 61 | self._base_url = HK_INDUSTRY_LIST 62 | elif 'US' == self.market: 63 | self._base_url = US_INDUSTRY_LIST 64 | else: 65 | raise RuntimeError('only support {}'.format(['US', 'CN', 'HK'])) 66 | 67 | @property 68 | def url(self): 69 | param = dict(self.kwargs) 70 | param['_'] = time.time() 71 | 72 | return self._base_url + ABuFixes.urlencode(param) 73 | 74 | 75 | class StockListUrl(IndustryUrl): 76 | def init_base_url(self): 77 | if 'CN' == self.market: 78 | self._base_url = CN_STOCK_LIST 79 | elif 'HK' == self.market: 80 | self._base_url = HK_STOCK_LIST 81 | elif 'US' == self.market: 82 | self._base_url = US_STOCK_LIST 83 | else: 84 | raise RuntimeError('only support {}'.format(['US', 'CN', 'HK'])) 85 | 86 | 87 | def test(): 88 | print(IndustryUrl('CN', plate='保险业', page=1, level2code='J68').url) 89 | print(IndustryUrl('US', plate='金融', page=1).url) 90 | print(IndustryUrl('HK', plate='保险', page=1).url) 91 | -------------------------------------------------------------------------------- /abupy/CrawlBu/ABuXqConsts.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | from __future__ import print_function 3 | from __future__ import absolute_import 4 | from __future__ import division 5 | 6 | __author__ = '小青蛙' 7 | __weixin__ = 'abu_quant' 8 | 9 | """ 10 | s:static 11 | d:dynamic 12 | co: company 13 | pb: price book ratio 14 | pe: price earning ratio 15 | ps: price sales ratio 16 | asset : net_asset_value_per_share 17 | oo:organization_ownership 18 | cc:circulation_capital 19 | mv:market_value 20 | sc:short_covering 21 | """ 22 | columns_map = { 23 | "symbol": 'symbol', 24 | "market": 'market', 25 | "exchange": 'exchange', 26 | 27 | "industry": 'industry', 28 | "name": 'co_name', 29 | "公司网站:": 'co_site', 30 | "公司电话:": 'co_tel', 31 | "公司地址:": 'co_addr', 32 | "业务:": 'co_business', 33 | "简介:": 'co_intro', 34 | 35 | "市盈率(静)/(动):": 'pe_s_d', 36 | "市净率(动):": 'pb_d', 37 | "市净率MRQ:": 'pb_MRQ', 38 | "市销率(动):": 'ps_d', 39 | "市销率:": 'ps', 40 | "市盈率(静):": 'pe_s', 41 | "换手率:": 'turnover', 42 | 43 | "每股净资产:": 'asset', 44 | "流通股本:": 'cc', 45 | "振幅:": 'amplitude', 46 | "空头补回天数:": 'sc', 47 | "招股说明书:": 'prospectus', 48 | "总股本:": 'equity', 49 | "总市值:": 'mv', 50 | "机构持股:": 'oo', 51 | "港股股本:": 'hk_equity' 52 | } 53 | -------------------------------------------------------------------------------- /abupy/CrawlBu/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/abupy/CrawlBu/__init__.py -------------------------------------------------------------------------------- /abupy/DLBu/ABuDL.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | # noinspection PyUnresolvedReferences 4 | from .ABuDLImgStd import * 5 | # noinspection PyUnresolvedReferences 6 | from .ABuDLTVSplit import * 7 | -------------------------------------------------------------------------------- /abupy/DLBu/ABuDLImgStd.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | """ 3 | 深度学习工具模块,为caffe等工具库标准化图片格式 4 | """ 5 | 6 | from __future__ import absolute_import 7 | from __future__ import print_function 8 | from __future__ import division 9 | 10 | import glob 11 | import imghdr 12 | import os 13 | 14 | import PIL.Image 15 | from PIL import ImageFile 16 | 17 | # noinspection PyUnresolvedReferences 18 | from ..CoreBu.ABuFixes import map 19 | 20 | from ..UtilBu import ABuFileUtil 21 | 22 | __all__ = ['std_img_from_root_dir', 23 | 'covert_to_jpeg', 24 | 'find_img_by_ext', 25 | 'change_to_real_type' 26 | ] 27 | 28 | __author__ = '阿布' 29 | __weixin__ = 'abu_quant' 30 | 31 | # 为了im.convert('RGB')的异常错误,需要设置ImageFile.LOAD_TRUNCATED_IMAGES = True 32 | ImageFile.LOAD_TRUNCATED_IMAGES = True 33 | 34 | 35 | def std_img_from_root_dir(root_dir, a_ext): 36 | """ 37 | 找到root_dir目录下所有.ext的图片,都转换其真实类型后, 38 | 将不是jpeg的全部转换为jpeg,即标准化图像格式 39 | :param root_dir: str对象,文件夹路径信息 40 | :param a_ext: 图像文件后缀,eg. png,jpg 41 | """ 42 | 43 | # root_dir目录下及一级子目录下所有.ext后缀的文件全路径返回 44 | img_list = find_img_by_ext(a_ext, root_dir) 45 | # img_list中所有的转换为其真实类型 46 | all_type = change_to_real_type(img_list) 47 | for ext in all_type: 48 | # 迭代change_to_real_type返回的集合 49 | if ext != 'jpeg': 50 | # 标准化所有输入图片,将不是jpeg的都转换为jpeg 51 | if ext is None: 52 | ext = a_ext 53 | # 找到非标准类型子序列sub_img_list 54 | sub_img_list = find_img_by_ext(ext, root_dir) 55 | # 一个个进行转换 56 | _ = list(map(lambda img: covert_to_jpeg(img), sub_img_list)) 57 | # 然后再次转换其真实后缀名 58 | change_to_real_type(sub_img_list) 59 | 60 | 61 | def covert_to_jpeg(org_img, dst_img=None): 62 | """ 63 | 将输入img转换为RGB的jpeg格式图像 64 | :param org_img: 原始图像路径,str对象 65 | :param dst_img: 转换后的图像路径输出路径,str对象,默认=None将覆盖org_img路径 66 | """ 67 | im = PIL.Image.open(org_img) 68 | if dst_img is None: 69 | # 不设置输出路径,即在输入文件上直接覆盖 70 | dst_img = org_img 71 | im.convert('RGB').save(dst_img, 'JPEG') 72 | 73 | 74 | def find_img_by_ext(ext, root_dir): 75 | """ 76 | 将root_dir目录下及一级子目录下所有.ext后缀的文件全路径返回, 77 | 注意只遍历根目录及一级子目录 78 | :param ext: str对象 图像文件后缀,eg. png,jpg 79 | :param root_dir: str对象,文件夹路径信息 80 | :return: list序列对象 81 | """ 82 | 83 | # 遍历一级子目录 84 | dirs = [root_dir + name for name in os.listdir(root_dir) if os.path.isdir(os.path.join(root_dir, name))] 85 | # 形成根目录及一级子目录 86 | dirs.append(root_dir) 87 | img_list = list() 88 | for dr in dirs: 89 | # 遍历所有目录,通过glob模糊查询所有.ext文件 90 | sub_list = glob.glob('{}/*.{}'.format(dr, ext)) 91 | img_list.extend(sub_list) 92 | return img_list 93 | 94 | 95 | def change_to_real_type(img_list): 96 | """ 97 | 将img的后缀名转换为其真实类型 98 | eg. a.png 如果 a.png实际上是jpeg,则将后缀修改-> a.jpeg 99 | :param img_list: 100 | :return: 101 | """ 102 | # 类型记录集合 103 | record_type = set() 104 | for img in img_list: 105 | if not ABuFileUtil.file_exist(img): 106 | # 过滤实际不存在的文件 107 | continue 108 | 109 | # 使用imghdr识别图像真实类型 110 | real_type = imghdr.what(img) 111 | # 将img_list有的类型做记录,add到集合中 112 | record_type.add(real_type) 113 | if real_type is None: 114 | # 识别不出来,可能就是残图,过滤 115 | continue 116 | # 修改成真实的类型 117 | real_name = img[:img.rfind('.')] + '.' + real_type 118 | os.rename(img, real_name) 119 | return record_type 120 | -------------------------------------------------------------------------------- /abupy/DLBu/ABuDLTVSplit.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | """ 3 | 深度学习工具模块,为caffe工具库做数据集准备, 4 | 切割训练集 5 | """ 6 | 7 | from __future__ import absolute_import 8 | from __future__ import print_function 9 | from __future__ import division 10 | 11 | from collections import defaultdict 12 | import itertools 13 | import os 14 | 15 | __author__ = '阿布' 16 | __weixin__ = 'abu_quant' 17 | 18 | __all__ = ['train_val_split'] 19 | 20 | 21 | def train_val_split(train_path, n_folds=10): 22 | """将caffe返回的数据集文件进行切割工作,切割为训练集,交叉测试集,测试集数据文件""" 23 | 24 | if n_folds <= 1: 25 | raise ValueError('n_folds must > 1') 26 | 27 | with open(train_path, 'r') as f: 28 | lines = f.readlines() 29 | class_dict = defaultdict(list) 30 | for line in lines: 31 | cs = line[line.rfind(' '):] 32 | class_dict[cs].append(line) 33 | 34 | train = list() 35 | val = list() 36 | for cs in class_dict: 37 | cs_len = len(class_dict[cs]) 38 | val_cnt = int(cs_len / n_folds) 39 | val.append(class_dict[cs][:val_cnt]) 40 | train.append(class_dict[cs][val_cnt:]) 41 | val = list(itertools.chain.from_iterable(val)) 42 | train = list(itertools.chain.from_iterable(train)) 43 | test = [t.split(' ')[0] + '\n' for t in val] 44 | 45 | # 在参数的train_path同目录下写train_split.txt 46 | fn = os.path.dirname(train_path) + '/train_split.txt' 47 | with open(fn, 'wb') as f: 48 | f.writelines(train) 49 | # 在参数的train_path同目录下写val_split.txt 50 | fn = os.path.dirname(train_path) + '/val_split.txt' 51 | with open(fn, 'wb') as f: 52 | f.writelines(val) 53 | # 在参数的train_path同目录下写/test_split.txt 54 | fn = os.path.dirname(train_path) + '/test_split.txt' 55 | with open(fn, 'wb') as f: 56 | f.writelines(test) 57 | -------------------------------------------------------------------------------- /abupy/DLBu/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | # import ABuDLImgStd 4 | # import ABuDLTVSplit 5 | from . import ABuDL as dl 6 | 7 | __all__ = [ 8 | 'dl', 9 | ] 10 | -------------------------------------------------------------------------------- /abupy/DLBu/pb/solver.prototxt: -------------------------------------------------------------------------------- 1 | net: "/Users/Bailey/Desktop/my_work/abu/Caffe/pb/train_val.prototxt" 2 | test_iter: 100 3 | test_interval: 2000 4 | test_initialization: false 5 | display: 100 6 | average_loss: 40 7 | base_lr: 0.01 8 | lr_policy: "step" 9 | stepsize: 320000 10 | gamma: 0.96 11 | max_iter: 2000000 12 | momentum: 0.9 13 | weight_decay: 0.0002 14 | snapshot: 6000 15 | snapshot_prefix: "/Users/Bailey/Desktop/my_work/abu/Caffe/gen/stock_judge_train" 16 | solver_mode: CPU 17 | -------------------------------------------------------------------------------- /abupy/DLBu/sh/Lmdb.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | echo "Begin..." 3 | ROOTFOLDER=$1 4 | OUTPUT=$2 5 | 6 | echo $ROOTFOLDER 7 | echo $OUTPUT 8 | 9 | ROOTFOLDER=/Users/Bailey/Desktop/my_work/abu/data/save_png/2016-10-09/ 10 | 11 | OUTPUT=/Users/Bailey/Desktop/my_work/abu/Caffe/gen 12 | 13 | rm -rf $OUTPUT/img_train_lmdb 14 | /Users/Bailey/caffe/build/tools/convert_imageset --shuffle \ 15 | --resize_height=256 --resize_width=256 \ 16 | $ROOTFOLDER $OUTPUT/train_split.txt $OUTPUT/img_train_lmdb 17 | 18 | rm -rf $OUTPUT/img_val_lmdb 19 | /Users/Bailey/caffe/build/tools/convert_imageset --shuffle \ 20 | --resize_height=256 --resize_width=256 \ 21 | $ROOTFOLDER $OUTPUT/val_split.txt $OUTPUT/img_val_lmdb 22 | echo "Done.." 23 | 24 | 25 | -------------------------------------------------------------------------------- /abupy/DLBu/sh/Mean.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | echo "Begin..." 3 | 4 | LMDB=../gen/img_train_lmdb 5 | MEANBIN=/Users/Bailey/caffe/build/tools/compute_image_mean 6 | OUTPUT=../gen/mean.binaryproto 7 | 8 | echo $OUTPUT 9 | 10 | $MEANBIN $LMDB $OUTPUT 11 | 12 | LMDB=../gen/img_val_lmdb 13 | OUTPUT=../gen/mean_val.binaryproto 14 | echo $OUTPUT 15 | $MEANBIN $LMDB $OUTPUT 16 | 17 | echo "Done.." -------------------------------------------------------------------------------- /abupy/DLBu/sh/Train.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | echo "Begin...." 3 | 4 | CAFEBIN=/Users/Bailey/caffe/build/tools/caffe 5 | SOLVER=../pb/solver.prototxt 6 | $CAFEBIN train -solver $SOLVER 7 | 8 | 9 | echo "Done" 10 | -------------------------------------------------------------------------------- /abupy/ExtBu/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | """ 3 | External, bundled dependencies. 4 | 5 | """ 6 | -------------------------------------------------------------------------------- /abupy/ExtBu/empyrical/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2016 Quantopian, Inc. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # flake8: noqa 16 | 17 | from ._version import get_versions 18 | __version__ = get_versions()['version'] 19 | del get_versions 20 | 21 | from .stats import ( 22 | cum_returns, 23 | cum_returns_final, 24 | aggregate_returns, 25 | max_drawdown, 26 | annual_return, 27 | annual_volatility, 28 | calmar_ratio, 29 | omega_ratio, 30 | sharpe_ratio, 31 | sortino_ratio, 32 | downside_risk, 33 | information_ratio, 34 | alpha_beta, 35 | alpha, 36 | beta, 37 | alpha_beta_aligned, 38 | alpha_aligned, 39 | beta_aligned, 40 | stability_of_timeseries, 41 | tail_ratio, 42 | cagr, 43 | DAILY, 44 | WEEKLY, 45 | MONTHLY, 46 | YEARLY 47 | ) 48 | -------------------------------------------------------------------------------- /abupy/ExtBu/empyrical/_version.py: -------------------------------------------------------------------------------- 1 | 2 | # This file was generated by 'versioneer.py' (0.16) from 3 | # revision-control system data, or from the parent directory name of an 4 | # unpacked source archive. Distribution tarballs contain a pre-generated copy 5 | # of this file. 6 | 7 | import json 8 | import sys 9 | 10 | version_json = ''' 11 | { 12 | "dirty": false, 13 | "error": null, 14 | "full-revisionid": "5d38634e0d68e65699383d2a97edaf34ce91fada", 15 | "version": "0.2.1" 16 | } 17 | ''' # END VERSION_JSON 18 | 19 | 20 | def get_versions(): 21 | return json.loads(version_json) 22 | -------------------------------------------------------------------------------- /abupy/ExtBu/empyrical/utils.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2016 Quantopian, Inc. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | try: 17 | # fast versions 18 | import bottleneck as bn 19 | nanmean = bn.nanmean 20 | nanstd = bn.nanstd 21 | nansum = bn.nansum 22 | nanmax = bn.nanmax 23 | nanmin = bn.nanmin 24 | nanargmax = bn.nanargmax 25 | nanargmin = bn.nanargmin 26 | except ImportError: 27 | # slower numpy 28 | import numpy as np 29 | nanmean = np.nanmean 30 | nanstd = np.nanstd 31 | nansum = np.nansum 32 | nanmax = np.nanmax 33 | nanmin = np.nanmin 34 | nanargmax = np.nanargmax 35 | nanargmin = np.nanargmin 36 | -------------------------------------------------------------------------------- /abupy/ExtBu/futures/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2009 Brian Quinlan. All Rights Reserved. 2 | # Licensed to PSF under a Contributor Agreement. 3 | 4 | """Execute computations asynchronously using threads or processes.""" 5 | 6 | __author__ = 'Brian Quinlan (brian@sweetapp.com)' 7 | 8 | from concurrent.futures._base import (FIRST_COMPLETED, 9 | FIRST_EXCEPTION, 10 | ALL_COMPLETED, 11 | CancelledError, 12 | TimeoutError, 13 | Future, 14 | Executor, 15 | wait, 16 | as_completed) 17 | from concurrent.futures.thread import ThreadPoolExecutor 18 | 19 | try: 20 | from concurrent.futures.process import ProcessPoolExecutor 21 | except ImportError: 22 | # some platforms don't have multiprocessing 23 | pass 24 | -------------------------------------------------------------------------------- /abupy/ExtBu/joblib/_compat.py: -------------------------------------------------------------------------------- 1 | """ 2 | Compatibility layer for Python 3/Python 2 single codebase 3 | """ 4 | import sys 5 | 6 | PY3_OR_LATER = sys.version_info[0] >= 3 7 | PY26 = sys.version_info[:2] == (2, 6) 8 | PY27 = sys.version_info[:2] == (2, 7) 9 | 10 | try: 11 | _basestring = basestring 12 | _bytes_or_unicode = (str, unicode) 13 | except NameError: 14 | _basestring = str 15 | _bytes_or_unicode = (bytes, str) 16 | 17 | 18 | def with_metaclass(meta, *bases): 19 | """Create a base class with a metaclass.""" 20 | return meta("NewBase", bases, {}) 21 | -------------------------------------------------------------------------------- /abupy/ExtBu/joblib/_memory_helpers.py: -------------------------------------------------------------------------------- 1 | try: 2 | # Available in Python 3 3 | from tokenize import open as open_py_source 4 | 5 | except ImportError: 6 | # Copied from python3 tokenize 7 | from codecs import lookup, BOM_UTF8 8 | import re 9 | from io import TextIOWrapper, open 10 | cookie_re = re.compile("coding[:=]\s*([-\w.]+)") 11 | 12 | def _get_normal_name(orig_enc): 13 | """Imitates get_normal_name in tokenizer.c.""" 14 | # Only care about the first 12 characters. 15 | enc = orig_enc[:12].lower().replace("_", "-") 16 | if enc == "utf-8" or enc.startswith("utf-8-"): 17 | return "utf-8" 18 | if enc in ("latin-1", "iso-8859-1", "iso-latin-1") or \ 19 | enc.startswith(("latin-1-", "iso-8859-1-", "iso-latin-1-")): 20 | return "iso-8859-1" 21 | return orig_enc 22 | 23 | def _detect_encoding(readline): 24 | """ 25 | The detect_encoding() function is used to detect the encoding that 26 | should be used to decode a Python source file. It requires one 27 | argment, readline, in the same way as the tokenize() generator. 28 | 29 | It will call readline a maximum of twice, and return the encoding used 30 | (as a string) and a list of any lines (left as bytes) it has read in. 31 | 32 | It detects the encoding from the presence of a utf-8 bom or an encoding 33 | cookie as specified in pep-0263. If both a bom and a cookie are 34 | present, but disagree, a SyntaxError will be raised. If the encoding 35 | cookie is an invalid charset, raise a SyntaxError. Note that if a 36 | utf-8 bom is found, 'utf-8-sig' is returned. 37 | 38 | If no encoding is specified, then the default of 'utf-8' will be 39 | returned. 40 | """ 41 | bom_found = False 42 | encoding = None 43 | default = 'utf-8' 44 | 45 | def read_or_stop(): 46 | try: 47 | return readline() 48 | except StopIteration: 49 | return b'' 50 | 51 | def find_cookie(line): 52 | try: 53 | line_string = line.decode('ascii') 54 | except UnicodeDecodeError: 55 | return None 56 | 57 | matches = cookie_re.findall(line_string) 58 | if not matches: 59 | return None 60 | encoding = _get_normal_name(matches[0]) 61 | try: 62 | codec = lookup(encoding) 63 | except LookupError: 64 | # This behaviour mimics the Python interpreter 65 | raise SyntaxError("unknown encoding: " + encoding) 66 | 67 | if bom_found: 68 | if codec.name != 'utf-8': 69 | # This behaviour mimics the Python interpreter 70 | raise SyntaxError('encoding problem: utf-8') 71 | encoding += '-sig' 72 | return encoding 73 | 74 | first = read_or_stop() 75 | if first.startswith(BOM_UTF8): 76 | bom_found = True 77 | first = first[3:] 78 | default = 'utf-8-sig' 79 | if not first: 80 | return default, [] 81 | 82 | encoding = find_cookie(first) 83 | if encoding: 84 | return encoding, [first] 85 | 86 | second = read_or_stop() 87 | if not second: 88 | return default, [first] 89 | 90 | encoding = find_cookie(second) 91 | if encoding: 92 | return encoding, [first, second] 93 | 94 | return default, [first, second] 95 | 96 | def open_py_source(filename): 97 | """Open a file in read only mode using the encoding detected by 98 | detect_encoding(). 99 | """ 100 | buffer = open(filename, 'rb') 101 | encoding, lines = _detect_encoding(buffer.readline) 102 | buffer.seek(0) 103 | text = TextIOWrapper(buffer, encoding, line_buffering=True) 104 | text.mode = 'r' 105 | return text -------------------------------------------------------------------------------- /abupy/ExtBu/joblib/_multiprocessing_helpers.py: -------------------------------------------------------------------------------- 1 | """Helper module to factorize the conditional multiprocessing import logic 2 | 3 | We use a distinct module to simplify import statements and avoid introducing 4 | circular dependencies (for instance for the assert_spawning name). 5 | """ 6 | import os 7 | import warnings 8 | 9 | 10 | # Obtain possible configuration from the environment, assuming 1 (on) 11 | # by default, upon 0 set to None. Should instructively fail if some non 12 | # 0/1 value is set. 13 | mp = int(os.environ.get('JOBLIB_MULTIPROCESSING', 1)) or None 14 | if mp: 15 | try: 16 | import multiprocessing as mp 17 | except ImportError: 18 | mp = None 19 | 20 | # 2nd stage: validate that locking is available on the system and 21 | # issue a warning if not 22 | if mp is not None: 23 | try: 24 | _sem = mp.Semaphore() 25 | del _sem # cleanup 26 | except (ImportError, OSError) as e: 27 | mp = None 28 | warnings.warn('%s. joblib will operate in serial mode' % (e,)) 29 | 30 | 31 | # 3rd stage: backward compat for the assert_spawning helper 32 | if mp is not None: 33 | try: 34 | # Python 3.4+ 35 | from multiprocessing.context import assert_spawning 36 | except ImportError: 37 | from multiprocessing.forking import assert_spawning 38 | else: 39 | assert_spawning = None 40 | -------------------------------------------------------------------------------- /abupy/ExtBu/joblib/disk.py: -------------------------------------------------------------------------------- 1 | """ 2 | Disk management utilities. 3 | """ 4 | 5 | # Authors: Gael Varoquaux 6 | # Lars Buitinck 7 | # Copyright (c) 2010 Gael Varoquaux 8 | # License: BSD Style, 3 clauses. 9 | 10 | 11 | import errno 12 | import os 13 | import shutil 14 | import sys 15 | import time 16 | 17 | 18 | def disk_used(path): 19 | """ Return the disk usage in a directory.""" 20 | size = 0 21 | for file in os.listdir(path) + ['.']: 22 | stat = os.stat(os.path.join(path, file)) 23 | if hasattr(stat, 'st_blocks'): 24 | size += stat.st_blocks * 512 25 | else: 26 | # on some platform st_blocks is not available (e.g., Windows) 27 | # approximate by rounding to next multiple of 512 28 | size += (stat.st_size // 512 + 1) * 512 29 | # We need to convert to int to avoid having longs on some systems (we 30 | # don't want longs to avoid problems we SQLite) 31 | return int(size / 1024.) 32 | 33 | 34 | def memstr_to_bytes(text): 35 | """ Convert a memory text to its value in bytes. 36 | """ 37 | kilo = 1024 38 | units = dict(K=kilo, M=kilo ** 2, G=kilo ** 3) 39 | try: 40 | size = int(units[text[-1]] * float(text[:-1])) 41 | except (KeyError, ValueError): 42 | raise ValueError( 43 | "Invalid literal for size give: %s (type %s) should be " 44 | "alike '10G', '500M', '50K'." % (text, type(text))) 45 | return size 46 | 47 | 48 | def mkdirp(d): 49 | """Ensure directory d exists (like mkdir -p on Unix) 50 | No guarantee that the directory is writable. 51 | """ 52 | try: 53 | os.makedirs(d) 54 | except OSError as e: 55 | if e.errno != errno.EEXIST: 56 | raise 57 | 58 | 59 | # if a rmtree operation fails in rm_subdirs, wait for this much time (in secs), 60 | # then retry once. if it still fails, raise the exception 61 | RM_SUBDIRS_RETRY_TIME = 0.1 62 | 63 | 64 | def rm_subdirs(path, onerror=None): 65 | """Remove all subdirectories in this path. 66 | 67 | The directory indicated by `path` is left in place, and its subdirectories 68 | are erased. 69 | 70 | If onerror is set, it is called to handle the error with arguments (func, 71 | path, exc_info) where func is os.listdir, os.remove, or os.rmdir; 72 | path is the argument to that function that caused it to fail; and 73 | exc_info is a tuple returned by sys.exc_info(). If onerror is None, 74 | an exception is raised. 75 | """ 76 | 77 | # NOTE this code is adapted from the one in shutil.rmtree, and is 78 | # just as fast 79 | 80 | names = [] 81 | try: 82 | names = os.listdir(path) 83 | except os.error as err: 84 | if onerror is not None: 85 | onerror(os.listdir, path, sys.exc_info()) 86 | else: 87 | raise 88 | 89 | for name in names: 90 | fullname = os.path.join(path, name) 91 | if os.path.isdir(fullname): 92 | if onerror is not None: 93 | shutil.rmtree(fullname, False, onerror) 94 | else: 95 | # allow the rmtree to fail once, wait and re-try. 96 | # if the error is raised again, fail 97 | err_count = 0 98 | while True: 99 | try: 100 | shutil.rmtree(fullname, False, None) 101 | break 102 | except os.error: 103 | if err_count > 0: 104 | raise 105 | err_count += 1 106 | time.sleep(RM_SUBDIRS_RETRY_TIME) 107 | -------------------------------------------------------------------------------- /abupy/ExtBu/joblib/testing.py: -------------------------------------------------------------------------------- 1 | """ 2 | Helper for testing. 3 | """ 4 | 5 | import sys 6 | import warnings 7 | import os.path 8 | import re 9 | import subprocess 10 | import threading 11 | 12 | from sklearn.externals.joblib._compat import PY3_OR_LATER 13 | 14 | 15 | def warnings_to_stdout(): 16 | """ Redirect all warnings to stdout. 17 | """ 18 | showwarning_orig = warnings.showwarning 19 | 20 | def showwarning(msg, cat, fname, lno, file=None, line=0): 21 | showwarning_orig(msg, cat, os.path.basename(fname), line, sys.stdout) 22 | 23 | warnings.showwarning = showwarning 24 | #warnings.simplefilter('always') 25 | 26 | 27 | try: 28 | from nose.tools import assert_raises_regex 29 | except ImportError: 30 | # For Python 2.7 31 | try: 32 | from nose.tools import assert_raises_regexp as assert_raises_regex 33 | except ImportError: 34 | # for Python 2.6 35 | def assert_raises_regex(expected_exception, expected_regexp, 36 | callable_obj=None, *args, **kwargs): 37 | """Helper function to check for message patterns in exceptions""" 38 | 39 | not_raised = False 40 | try: 41 | callable_obj(*args, **kwargs) 42 | not_raised = True 43 | except Exception as e: 44 | error_message = str(e) 45 | if not re.compile(expected_regexp).search(error_message): 46 | raise AssertionError("Error message should match pattern " 47 | "%r. %r does not." % 48 | (expected_regexp, error_message)) 49 | if not_raised: 50 | raise AssertionError("Should have raised %r" % 51 | expected_exception(expected_regexp)) 52 | 53 | 54 | def check_subprocess_call(cmd, timeout=1, stdout_regex=None, 55 | stderr_regex=None): 56 | """Runs a command in a subprocess with timeout in seconds. 57 | 58 | Also checks returncode is zero, stdout if stdout_regex is set, and 59 | stderr if stderr_regex is set. 60 | """ 61 | proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, 62 | stderr=subprocess.PIPE) 63 | 64 | def kill_process(): 65 | proc.kill() 66 | 67 | timer = threading.Timer(timeout, kill_process) 68 | try: 69 | timer.start() 70 | stdout, stderr = proc.communicate() 71 | 72 | if PY3_OR_LATER: 73 | stdout, stderr = stdout.decode(), stderr.decode() 74 | if proc.returncode != 0: 75 | message = ( 76 | 'Non-zero return code: {0}.\nStdout:\n{1}\n' 77 | 'Stderr:\n{2}').format( 78 | proc.returncode, stdout, stderr) 79 | raise ValueError(message) 80 | 81 | if (stdout_regex is not None and 82 | not re.search(stdout_regex, stdout)): 83 | raise ValueError( 84 | "Unexpected stdout: {0!r} does not match:\n{1!r}".format( 85 | stdout_regex, stdout)) 86 | if (stderr_regex is not None and 87 | not re.search(stderr_regex, stderr)): 88 | raise ValueError( 89 | "Unexpected stderr: {0!r} does not match:\n{1!r}".format( 90 | stderr_regex, stderr)) 91 | 92 | finally: 93 | timer.cancel() 94 | -------------------------------------------------------------------------------- /abupy/FactorBuyBu/ABuBuyFactorWrap.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | """买入因子类装饰器模块""" 3 | 4 | from __future__ import absolute_import 5 | from __future__ import print_function 6 | from __future__ import division 7 | 8 | from ..CoreBu.ABuFixes import six 9 | from ..TLineBu.ABuTL import AbuTLine 10 | 11 | __author__ = '阿布' 12 | __weixin__ = 'abu_quant' 13 | 14 | 15 | class AbuLeastPolyWrap(object): 16 | """示例做为买入因子策略装饰器封装show_least_valid_poly对大盘震荡大的情况下封锁交易""" 17 | 18 | def __call__(self, cls): 19 | """只做为买入因子策略类的装饰器""" 20 | 21 | if isinstance(cls, six.class_types): 22 | # 只做为类装饰器使用 23 | 24 | init_self = cls._init_self 25 | org_fit_day = cls.fit_day 26 | 27 | # fit_month不是必须实现的 28 | org_fit_month = getattr(cls, 'fit_month', None) 29 | 30 | def init_self_wrapped(*args, **kwargs): 31 | # 拿出被装饰的self对象 32 | warp_self = args[0] 33 | # 外部可以设置poly阀值,self.poly在fit_month中和每一个月大盘计算的poly比较, 34 | # 若是大盘的poly大于poly认为走势震荡 35 | warp_self.poly = kwargs.pop('poly', 2) 36 | # 是否封锁买入策略进行择时交易 37 | warp_self.lock = False 38 | # 调用原始的_init_self 39 | init_self(*args, **kwargs) 40 | 41 | def fit_day_wrapped(*args, **kwargs): 42 | # 拿出被装饰的self对象 43 | warp_self = args[0] 44 | if warp_self.lock: 45 | # 如果封锁策略进行交易的情况下,策略不进行择时 46 | return None 47 | return org_fit_day(*args, **kwargs) 48 | 49 | def fit_month_wrapped(*args, **kwargs): 50 | warp_self = args[0] 51 | today = args[1] 52 | # fit_month即在回测策略中每一个月执行一次的方法 53 | # 策略中拥有self.benchmark,即交易基准对象,AbuBenchmark实例对象,benchmark.kl_pd即对应的市场大盘走势 54 | benchmark_df = warp_self.benchmark.kl_pd 55 | # 拿出大盘的今天 56 | benchmark_today = benchmark_df[benchmark_df.date == today.date] 57 | if benchmark_today.empty: 58 | return 0 59 | # 要拿大盘最近一个月的走势,准备切片的start,end 60 | end_key = int(benchmark_today.iloc[0].key) 61 | start_key = end_key - 20 62 | if start_key < 0: 63 | return 0 64 | 65 | # 使用切片切出从今天开始向前20天的数据 66 | benchmark_month = benchmark_df[start_key:end_key + 1] 67 | # 通过大盘最近一个月的收盘价格做为参数构造AbuTLine对象 68 | benchmark_month_line = AbuTLine(benchmark_month.close, 'benchmark month line') 69 | # 计算这个月最少需要几次拟合才能代表走势曲线 70 | least = benchmark_month_line.show_least_valid_poly(show=False) 71 | 72 | if least >= warp_self.poly: 73 | # 如果最少的拟合次数大于阀值self.poly,说明走势成立,大盘非震荡走势,解锁交易 74 | warp_self.lock = False 75 | else: 76 | # 如果最少的拟合次数小于阀值self.poly,说明大盘处于震荡走势,封锁策略进行交易 77 | warp_self.lock = True 78 | 79 | if org_fit_month is not None: 80 | return org_fit_month(*args, **kwargs) 81 | 82 | cls._init_self = init_self_wrapped 83 | init_self_wrapped.__name__ = '_init_self' 84 | 85 | cls.fit_day = fit_day_wrapped 86 | fit_day_wrapped.__name__ = 'fit_day' 87 | 88 | cls.fit_month = fit_month_wrapped 89 | fit_month_wrapped.__name__ = 'fit_month' 90 | 91 | return cls 92 | else: 93 | raise TypeError('AbuLeastPolyWrap just for class warp') 94 | -------------------------------------------------------------------------------- /abupy/FactorBuyBu/ABuFactorBuyBreak.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | """ 3 | 买入择时示例因子:突破买入择时因子 4 | """ 5 | 6 | from __future__ import absolute_import 7 | from __future__ import print_function 8 | from __future__ import division 9 | 10 | from .ABuFactorBuyBase import AbuFactorBuyBase, AbuFactorBuyXD, BuyCallMixin, BuyPutMixin 11 | 12 | __author__ = '阿布' 13 | __weixin__ = 'abu_quant' 14 | 15 | 16 | # noinspection PyAttributeOutsideInit 17 | class AbuFactorBuyBreak(AbuFactorBuyBase, BuyCallMixin): 18 | """示例正向突破买入择时类,混入BuyCallMixin,即向上突破触发买入event""" 19 | 20 | def _init_self(self, **kwargs): 21 | """kwargs中必须包含: 突破参数xd 比如20,30,40天...突破""" 22 | # 突破参数 xd, 比如20,30,40天...突破, 不要使用kwargs.pop('xd', 20), 明确需要参数xq 23 | self.xd = kwargs['xd'] 24 | # 在输出生成的orders_pd中显示的名字 25 | self.factor_name = '{}:{}'.format(self.__class__.__name__, self.xd) 26 | 27 | def fit_day(self, today): 28 | """ 29 | 针对每一个交易日拟合买入交易策略,寻找向上突破买入机会 30 | :param today: 当前驱动的交易日金融时间序列数据 31 | :return: 32 | """ 33 | # 忽略不符合买入的天(统计周期内前xd天) 34 | if self.today_ind < self.xd - 1: 35 | return None 36 | 37 | # 今天的收盘价格达到xd天内最高价格则符合买入条件 38 | if today.close == self.kl_pd.close[self.today_ind - self.xd + 1:self.today_ind + 1].max(): 39 | # 把突破新高参数赋值skip_days,这里也可以考虑make_buy_order确定是否买单成立,但是如果停盘太长时间等也不好 40 | self.skip_days = self.xd 41 | # 生成买入订单, 由于使用了今天的收盘价格做为策略信号判断,所以信号发出后,只能明天买 42 | return self.buy_tomorrow() 43 | return None 44 | 45 | 46 | # noinspection PyAttributeOutsideInit 47 | class AbuFactorBuyXDBK(AbuFactorBuyXD, BuyCallMixin): 48 | """示例继承AbuFactorBuyXD完成正向突破买入择时类""" 49 | def fit_day(self, today): 50 | """ 51 | 针对每一个交易日拟合买入交易策略,寻找向上突破买入机会 52 | :param today: 当前驱动的交易日金融时间序列数据 53 | :return: 54 | """ 55 | # 今天的收盘价格达到xd天内最高价格则符合买入条件 56 | if today.close == self.xd_kl.close.max(): 57 | return self.buy_tomorrow() 58 | return None 59 | 60 | 61 | # noinspection PyAttributeOutsideInit 62 | class AbuFactorBuyPutBreak(AbuFactorBuyBase, BuyPutMixin): 63 | """示例反向突破买入择时类,混入BuyPutMixin,即向下突破触发买入event,详情请查阅期货回测示例demo""" 64 | 65 | def _init_self(self, **kwargs): 66 | """kwargs中必须包含: 突破参数xd 比如20,30,40天...突破""" 67 | 68 | # 突破参数 xd, 比如20,30,40天...突破, 不要使用kwargs.pop('xd', 20), 明确需要参数xq 69 | self.xd = kwargs['xd'] 70 | self.factor_name = '{}:{}'.format(self.__class__.__name__, self.xd) 71 | 72 | def fit_day(self, today): 73 | """ 74 | 针对每一个交易日拟合买入交易策略,寻找向下突破买入机会 75 | :param today: 当前驱动的交易日金融时间序列数据 76 | :return: 77 | """ 78 | # 忽略不符合买入的天(统计周期内前xd天) 79 | if self.today_ind < self.xd - 1: 80 | return None 81 | """ 82 | 与AbuFactorBuyBreak区别就是买向下突破的,即min() 83 | """ 84 | if today.close == self.kl_pd.close[self.today_ind - self.xd + 1:self.today_ind + 1].min(): 85 | self.skip_days = self.xd 86 | return self.buy_tomorrow() 87 | return None 88 | 89 | 90 | # noinspection PyAttributeOutsideInit 91 | class AbuFactorBuyPutXDBK(AbuFactorBuyXD, BuyPutMixin): 92 | """示例继承AbuFactorBuyXD完成反向突破买入择时类""" 93 | def fit_day(self, today): 94 | """ 95 | 针对每一个交易日拟合买入交易策略,寻找向上突破买入机会 96 | :param today: 当前驱动的交易日金融时间序列数据 97 | :return: 98 | """ 99 | # 与AbuFactorBuyBreak区别就是买向下突破的,即min() 100 | if today.close == self.xd_kl.close.min(): 101 | return self.buy_tomorrow() 102 | return None 103 | -------------------------------------------------------------------------------- /abupy/FactorBuyBu/ABuFactorBuyWD.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | """ 3 | 买入择时示例因子:日胜率均值买入择时因子 4 | """ 5 | 6 | from __future__ import absolute_import 7 | from __future__ import print_function 8 | from __future__ import division 9 | 10 | from .ABuFactorBuyBase import AbuFactorBuyTD, BuyCallMixin 11 | 12 | __author__ = '阿布' 13 | __weixin__ = 'abu_quant' 14 | 15 | 16 | class AbuFactorBuyWD(AbuFactorBuyTD, BuyCallMixin): 17 | """ 18 | 示例短线:日胜率均值回复策略 19 | 20 | 1. 默认以40天为周期(8周)结合涨跌阀值计算周几适合买入 21 | 2. 回测运行中每一月重新计算一次上述的周几适合买入 22 | 3. 在策略日任务中买入信号为:昨天下跌,今天开盘也下跌,且明天是计算出来的上涨概率大的'周几' 23 | """ 24 | 25 | def _init_self(self, **kwargs): 26 | """ 27 | kwargs中可选参数:buy_dw: 代表周期胜率阀值,默认0.55即55% 28 | kwargs中可选参数:buy_dwm: 代表涨幅比例阀值系数,默认0.618 29 | kwargs中可选参数:dw_period: 代表分析dw,dwm所使用的交易周期,默认40天周期(8周) 30 | """ 31 | self.buy_dw = kwargs.pop('buy_dw', 0.55) 32 | self.buy_dwm = kwargs.pop('buy_dwm', 0.618) 33 | self.dw_period = kwargs.pop('dw_period', 40) 34 | 35 | # combine_kl_pd中包含择时金融时间数据与择时之前周期的金融时间数据, 先取出择时开始之前的周期数据 36 | last_kl = self.combine_kl_pd.loc[:self.kl_pd.index[0]] 37 | if last_kl.shape[0] > self.dw_period: 38 | last_kl = last_kl[-self.dw_period:] 39 | # 开始计算周几买,_make_buy_date把结果被放在self.buy_date_week序列中 40 | self._make_buy_date(last_kl) 41 | 42 | def fit_month(self, today): 43 | """月任务,每一个重新取之前周期内的金融时间序列数据,重新计算一遍'周几买'""" 44 | last_kl = self.past_today_kl(today, self.dw_period) 45 | # 重新计算一遍'周几买' 46 | self._make_buy_date(last_kl) 47 | 48 | def fit_day(self, today): 49 | """日任务:昨天下跌,今天开盘也下跌,根据今天是周几,在不在序列self.buy_date_week中决定今天买不买""" 50 | if self.yesterday.p_change < 0 and today.open < self.yesterday.close \ 51 | and int(today.date_week) in self.buy_date_week: 52 | # 由于没有用到今天的收盘价格等,可以直接使用buy_today 53 | return self.buy_today() 54 | return None 55 | 56 | # noinspection PyProtectedMember 57 | def _make_buy_date(self, last_kl): 58 | """ 59 | 根据金融时间周期数据切片具体计算'周几'买上涨概率大 60 | 61 | :param last_kl: 金融时间周期数据切片,pd.DataFrame 62 | """ 63 | from ..UtilBu import ABuKLUtil 64 | 65 | self.buy_date_week = [] 66 | # 计算周期内,周期的胜率 67 | last_dw = ABuKLUtil.date_week_win(last_kl) 68 | # 摘取大于阀值self.buy_dw的'周几',buy_dw默认0.55 69 | last_dw_vd = last_dw[last_dw.win >= self.buy_dw] 70 | """ 71 | eg: last_dw_vd 72 | 0 1 win 73 | date_week 74 | 周四 3 5 0.62 75 | 周五 2 6 0.75 76 | """ 77 | if len(last_dw_vd) > 0: 78 | # 如果胜率有符合要求的,使用周几平均涨幅计算date_week_mean 79 | last_dwm = ABuKLUtil.date_week_mean(last_kl) 80 | # 摘取满足胜率的last_dw_vd 81 | last_dwm_vd = last_dwm.loc[last_dw_vd.index] 82 | """ 83 | eg: last_dwm_vd 84 | _p_change 85 | date_week 86 | 周四 1.55 87 | 周五 1.12 88 | """ 89 | # 阀值计算方式1 90 | dwm1 = abs(last_dwm.sum()).values[0] / self.buy_dwm 91 | # 阀值计算方式2 92 | dwm2 = abs(last_dwm._p_change).mean() / self.buy_dwm 93 | # 如果symbol多可以使用&的关系 94 | dm_effect = (last_dwm_vd._p_change > dwm1) | (last_dwm_vd._p_change > dwm2) 95 | buy_date_loc = last_dwm_vd[dm_effect].index 96 | """ 97 | eg: buy_date_loc 98 | Index(['周四', '周五'], dtype='object', name='date_week') 99 | """ 100 | if len(buy_date_loc) > 0: 101 | # 如果涨跌幅阀值也满足,tolist,eg:['周一', '周二', '周三', '周四', '周五'] 102 | dw_index = last_dw.index.tolist() 103 | # 如果是一周5个交易日的就是4,如果是比特币等7天交易日的就是6 104 | max_ind = len(dw_index) - 1 105 | for bdl in buy_date_loc: 106 | sell_ind = dw_index.index(bdl) 107 | buy_ind = sell_ind - 1 if sell_ind > 0 else max_ind 108 | self.buy_date_week.append(buy_ind) 109 | -------------------------------------------------------------------------------- /abupy/FactorBuyBu/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from .ABuFactorBuyBase import AbuFactorBuyBase, AbuFactorBuyXD, AbuFactorBuyTD, BuyCallMixin, BuyPutMixin 4 | from .ABuFactorBuyBreak import AbuFactorBuyBreak, AbuFactorBuyPutBreak 5 | from .ABuFactorBuyWD import AbuFactorBuyWD 6 | from .ABuFactorBuyDemo import AbuSDBreak, AbuTwoDayBuy, AbuWeekMonthBuy, AbuFactorBuyBreakUmpDemo 7 | from .ABuFactorBuyDemo import AbuFactorBuyBreakReocrdHitDemo, AbuFactorBuyBreakHitPredictDemo 8 | from .ABuFactorBuyDM import AbuDoubleMaBuy 9 | from .ABuFactorBuyTrend import AbuUpDownTrend, AbuDownUpTrend, AbuUpDownGolden 10 | 11 | __all__ = [ 12 | 'AbuFactorBuyBase', 13 | 'AbuFactorBuyXD', 14 | 'AbuFactorBuyTD', 15 | 'BuyCallMixin', 16 | 'BuyPutMixin', 17 | 'AbuFactorBuyBreak', 18 | 'AbuFactorBuyWD', 19 | 'AbuFactorBuyPutBreak', 20 | 'AbuFactorBuyBreakUmpDemo', 21 | 'AbuFactorBuyBreakReocrdHitDemo', 22 | 'AbuFactorBuyBreakHitPredictDemo', 23 | 'AbuSDBreak', 24 | 'AbuTwoDayBuy', 25 | 'AbuWeekMonthBuy', 26 | 'AbuDoubleMaBuy', 27 | 'AbuUpDownTrend', 28 | 'AbuDownUpTrend', 29 | 'AbuUpDownGolden' 30 | ] 31 | -------------------------------------------------------------------------------- /abupy/FactorSellBu/ABuFS.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | # noinspection PyUnresolvedReferences 4 | from . import ABuFactorCloseAtrNStop as close 5 | # noinspection PyUnresolvedReferences 6 | from . import ABuFactorPreAtrNStop as pre 7 | -------------------------------------------------------------------------------- /abupy/FactorSellBu/ABuFactorAtrNStop.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | """ 3 | 卖出择时示例因子:n倍atr(止盈止损)择时卖出策略 4 | """ 5 | 6 | from __future__ import absolute_import 7 | from __future__ import print_function 8 | from __future__ import division 9 | 10 | from .ABuFactorSellBase import AbuFactorSellBase, ESupportDirection 11 | 12 | __author__ = '阿布' 13 | __weixin__ = 'abu_quant' 14 | 15 | 16 | class AbuFactorAtrNStop(AbuFactorSellBase): 17 | """示例n倍atr(止盈止损)因子""" 18 | 19 | def _init_self(self, **kwargs): 20 | """ 21 | kwargs中可选参数stop_loss_n: 止损的atr倍数 22 | kwargs中可选参数stop_win_n: 止盈的atr倍数 23 | """ 24 | 25 | if 'stop_loss_n' in kwargs: 26 | # 设置止损的atr倍数 27 | self.stop_loss_n = kwargs['stop_loss_n'] 28 | # 在输出生成的orders_pd中及可视化等等显示的名字 29 | self.sell_type_extra_loss = '{}:stop_loss={}'.format(self.__class__.__name__, self.stop_loss_n) 30 | 31 | if 'stop_win_n' in kwargs: 32 | # 设置止盈的atr倍数 33 | self.stop_win_n = kwargs['stop_win_n'] 34 | # 在输出生成的orders_pd中及可视化等等显示的名字 35 | self.sell_type_extra_win = '{}:stop_win={}'.format(self.__class__.__name__, self.stop_win_n) 36 | 37 | def support_direction(self): 38 | """n倍atr(止盈止损)因子支持两个方向""" 39 | return [ESupportDirection.DIRECTION_CAll.value, ESupportDirection.DIRECTION_PUT.value] 40 | 41 | def fit_day(self, today, orders): 42 | """ 43 | 止盈event:截止今天相比买入时的收益 * 买入时的期望方向 > n倍atr 44 | 止损event:截止今天相比买入时的收益 * 买入时的期望方向 < -n倍atr 45 | :param today: 当前驱动的交易日金融时间序列数据 46 | :param orders: 买入择时策略中生成的订单序列 47 | :return: 48 | """ 49 | 50 | for order in orders: 51 | """ 52 | today.close - order.buy_price:截止今天相比买入时的收益, 53 | order.expect_direction:买单的方向,收益*方向=实际收益 54 | """ 55 | profit = (today.close - order.buy_price) * order.expect_direction 56 | # atr常数,示例使用今天的atr21与atr14和作为atr常数,亦可以使用其它组合常量的方式 57 | stop_base = today.atr21 + today.atr14 58 | if hasattr(self, 'stop_win_n') and profit > 0 and profit > self.stop_win_n * stop_base: 59 | # 满足止盈条件卖出股票, 即收益(profit) > n倍atr 60 | self.sell_type_extra = self.sell_type_extra_win 61 | # 由于使用了当天的close价格,所以明天才能卖出 62 | self.sell_tomorrow(order) 63 | 64 | if hasattr(self, 'stop_loss_n') and profit < 0 and profit < -self.stop_loss_n * stop_base: 65 | # 满足止损条件卖出股票, 即收益(profit) < -n倍atr 66 | self.sell_type_extra = self.sell_type_extra_loss 67 | order.fit_sell_order(self.today_ind, self) 68 | # 由于使用了当天的close价格,所以明天才能卖出 69 | self.sell_tomorrow(order) 70 | -------------------------------------------------------------------------------- /abupy/FactorSellBu/ABuFactorCloseAtrNStop.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | """ 3 | 卖出择时示例因子: 较小利润值 < 买入后最大收益价格 - 今日价格 < 较大利润值 -> 止盈卖出 4 | 只做为单边止盈因子使用,作为利润保护因子使用 5 | """ 6 | 7 | from __future__ import absolute_import 8 | from __future__ import print_function 9 | from __future__ import division 10 | 11 | from .ABuFactorSellBase import AbuFactorSellBase, ESupportDirection 12 | 13 | __author__ = '阿布' 14 | __weixin__ = 'abu_quant' 15 | 16 | 17 | """外部可通过如:abupy.fs.close.g_default_close_atr_n = 2.5来修改默认值""" 18 | g_default_close_atr_n = 3 19 | 20 | 21 | class AbuFactorCloseAtrNStop(AbuFactorSellBase): 22 | """示例利润保护因子(止盈)因子""" 23 | 24 | def _init_self(self, **kwargs): 25 | """kwargs中可选参数close_atr_n: 保护利润止赢倍数""" 26 | 27 | self.close_atr_n = g_default_close_atr_n 28 | if 'close_atr_n' in kwargs: 29 | # 设置保护利润止赢倍数 30 | self.close_atr_n = kwargs['close_atr_n'] 31 | self.sell_type_extra = '{}:close_atr_n={}'.format(self.__class__.__name__, self.close_atr_n) 32 | 33 | def support_direction(self): 34 | """单日最大跌幅n倍atr(止损)因子支持两个方向""" 35 | return [ESupportDirection.DIRECTION_CAll.value, ESupportDirection.DIRECTION_PUT.value] 36 | 37 | def fit_day(self, today, orders): 38 | """ 39 | 止盈event: 较小利润值 < 买入后最大收益价格 - 今日价格 < 较大利润值 40 | :param today: 当前驱动的交易日金融时间序列数据 41 | :param orders: 买入择时策略中生成的订单序列 42 | :return: 43 | """ 44 | 45 | for order in orders: 46 | # 通过order中的买入日期计算金融时间序列kl_pd中的index 47 | mask_date = self.kl_pd['date'] == order.buy_date 48 | start_ind = int(self.kl_pd[mask_date]['key'].values) 49 | end_ind = self.today_ind + 1 50 | 51 | """ 52 | 从买入日子开始计算到今天得到买入后最大收盘价格作为max_close, 53 | 注意如果是call找序列中的最大收盘价格,put找序列中的最小收盘价格 54 | """ 55 | max_close = self.kl_pd.iloc[start_ind:end_ind, :].close.max() if order.buy_type_str == 'call' \ 56 | else self.kl_pd.iloc[start_ind:end_ind, :].close.min() 57 | 58 | """ 59 | max_close - order.buy_price * 方向 > today['atr21']:代表只针对有一定盈利的情况生效,即 > 较小利润值 60 | max_close - today.close * 方向 > today['atr21'] * self.close_atr_n:下跌了一定值止盈退出, 即 < 较大利润值 61 | """ 62 | if (max_close - order.buy_price) * order.expect_direction > today['atr21'] \ 63 | and (max_close - today.close) * order.expect_direction > today['atr21'] * self.close_atr_n: 64 | # 由于使用了当天的close价格,所以明天才能卖出 65 | self.sell_tomorrow(order) 66 | -------------------------------------------------------------------------------- /abupy/FactorSellBu/ABuFactorPreAtrNStop.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | """ 3 | 卖出择时示例因子:单日最大跌幅n倍atr止损 4 | 做为单边止损因子使用,作为风险控制保护因子 5 | """ 6 | 7 | from __future__ import absolute_import 8 | from __future__ import print_function 9 | from __future__ import division 10 | 11 | from .ABuFactorSellBase import AbuFactorSellBase, ESupportDirection 12 | 13 | __author__ = '阿布' 14 | __weixin__ = 'abu_quant' 15 | 16 | """外部可通过如:abupy.fs.pre.g_default_pre_atr_n = 2.5来修改默认值""" 17 | g_default_pre_atr_n = 1.5 18 | 19 | 20 | class AbuFactorPreAtrNStop(AbuFactorSellBase): 21 | """示例单日最大跌幅n倍atr(止损)风险控制因子""" 22 | 23 | def _init_self(self, **kwargs): 24 | """kwargs中可选参数pre_atr_n: 单日最大跌幅止损的atr倍数""" 25 | 26 | self.pre_atr_n = g_default_pre_atr_n 27 | if 'pre_atr_n' in kwargs: 28 | # 设置下跌止损倍数 29 | self.pre_atr_n = kwargs['pre_atr_n'] 30 | self.sell_type_extra = '{}:pre_atr={}'.format(self.__class__.__name__, self.pre_atr_n) 31 | 32 | def support_direction(self): 33 | """单日最大跌幅n倍atr(止损)因子支持两个方向""" 34 | return [ESupportDirection.DIRECTION_CAll.value, ESupportDirection.DIRECTION_PUT.value] 35 | 36 | def fit_day(self, today, orders): 37 | """ 38 | 止损event:今天相比昨天的收益 * 买入时的期望方向 > today.atr21 * pre_atr_n 39 | :param today: 当前驱动的交易日金融时间序列数据 40 | :param orders: 买入择时策略中生成的订单序列 41 | :return: 42 | """ 43 | 44 | for order in orders: 45 | if (today.pre_close - today.close) * order.expect_direction > today.atr21 * self.pre_atr_n: 46 | # 只要今天的收盘价格比昨天收盘价格差大于一个差值就止损卖出, 亦可以使用其它计算差值方式 47 | self.sell_tomorrow(order) 48 | -------------------------------------------------------------------------------- /abupy/FactorSellBu/ABuFactorSellBreak.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | """ 3 | 卖出择时示例因子:突破卖出择时因子 4 | """ 5 | 6 | from __future__ import absolute_import 7 | from __future__ import print_function 8 | from __future__ import division 9 | 10 | from .ABuFactorSellBase import AbuFactorSellBase, AbuFactorSellXD, ESupportDirection 11 | 12 | __author__ = '阿布' 13 | __weixin__ = 'abu_quant' 14 | 15 | 16 | class AbuFactorSellBreak(AbuFactorSellBase): 17 | """示例向下突破卖出择时因子""" 18 | 19 | def _init_self(self, **kwargs): 20 | """kwargs中必须包含: 突破参数xd 比如20,30,40天...突破""" 21 | 22 | # 向下突破参数 xd, 比如20,30,40天...突破 23 | self.xd = kwargs['xd'] 24 | # 在输出生成的orders_pd中显示的名字 25 | self.sell_type_extra = '{}:{}'.format(self.__class__.__name__, self.xd) 26 | 27 | def support_direction(self): 28 | """支持的方向,只支持正向""" 29 | return [ESupportDirection.DIRECTION_CAll.value] 30 | 31 | def fit_day(self, today, orders): 32 | """ 33 | 寻找向下突破作为策略卖出驱动event 34 | :param today: 当前驱动的交易日金融时间序列数据 35 | :param orders: 买入择时策略中生成的订单序列 36 | """ 37 | # 今天的收盘价格达到xd天内最低价格则符合条件 38 | if today.close == self.kl_pd.close[self.today_ind - self.xd + 1:self.today_ind + 1].min(): 39 | for order in orders: 40 | self.sell_tomorrow(order) 41 | 42 | 43 | class AbuFactorSellXDBK(AbuFactorSellXD): 44 | """示例继承AbuFactorBuyXD, 向下突破卖出择时因子""" 45 | 46 | def support_direction(self): 47 | """支持的方向,只支持正向""" 48 | return [ESupportDirection.DIRECTION_CAll.value] 49 | 50 | def fit_day(self, today, orders): 51 | """ 52 | 寻找向下突破作为策略卖出驱动event 53 | :param today: 当前驱动的交易日金融时间序列数据 54 | :param orders: 买入择时策略中生成的订单序列 55 | """ 56 | # 今天的收盘价格达到xd天内最低价格则符合条件 57 | if today.close == self.xd_kl.close.min(): 58 | for order in orders: 59 | self.sell_tomorrow(order) 60 | -------------------------------------------------------------------------------- /abupy/FactorSellBu/ABuFactorSellDM.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | """ 3 | 卖出择时示例因子,双均线策略 4 | """ 5 | 6 | from __future__ import absolute_import 7 | from __future__ import print_function 8 | from __future__ import division 9 | 10 | from .ABuFactorSellBase import AbuFactorSellXD, ESupportDirection 11 | from ..IndicatorBu.ABuNDMa import calc_ma_from_prices 12 | 13 | __author__ = '阿布' 14 | __weixin__ = 'abu_quant' 15 | 16 | 17 | class AbuDoubleMaSell(AbuFactorSellXD): 18 | """示例卖出双均线择时因子""" 19 | 20 | def _init_self(self, **kwargs): 21 | """ 22 | kwargs中可选参数:fast: 均线快线周期,默认不设置,使用5 23 | kwargs中可选参数:slow: 均线慢线周期,默认不设置,使用60 24 | """ 25 | 26 | # TODO 重构与买入因子重复代码抽取 27 | # 均线快线周期,默认使用5天均线 28 | self.ma_fast = kwargs.pop('fast', 5) 29 | # 均线慢线周期,默认使用60天均线 30 | self.ma_slow = kwargs.pop('slow', 60) 31 | 32 | if self.ma_fast >= self.ma_slow: 33 | # 慢线周期必须大于快线 34 | raise ValueError('ma_fast >= self.ma_slow !') 35 | 36 | # xd周期数据需要比ma_slow大一天,这样计算ma就可以拿到今天和昨天两天的ma,用来判断金叉,死叉 37 | kwargs['xd'] = self.ma_slow + 1 38 | # 设置好xd后可以直接使用基类针对xd的初始化 39 | super(AbuDoubleMaSell, self)._init_self(**kwargs) 40 | 41 | def support_direction(self): 42 | """支持的方向,因子支持两个方向""" 43 | return [ESupportDirection.DIRECTION_CAll.value, ESupportDirection.DIRECTION_PUT.value] 44 | 45 | def fit_day(self, today, orders): 46 | """ 47 | 双均线卖出择时因子: 48 | call方向:快线下穿慢线形成死叉,做为卖出信号 49 | put方向: 快线上穿慢线做为卖出信号 50 | """ 51 | # 计算快线 52 | fast_line = calc_ma_from_prices(self.xd_kl.close, self.ma_fast, min_periods=1) 53 | # 计算慢线 54 | slow_line = calc_ma_from_prices(self.xd_kl.close, self.ma_slow, min_periods=1) 55 | 56 | if len(fast_line) >= 2 and len(slow_line) >= 2: 57 | # 今天的快线值 58 | fast_today = fast_line[-1] 59 | # 昨天的快线值 60 | fast_yesterday = fast_line[-2] 61 | # 今天的慢线值 62 | slow_today = slow_line[-1] 63 | # 昨天的慢线值 64 | slow_yesterday = slow_line[-2] 65 | 66 | for order in orders: 67 | if order.expect_direction == 1 \ 68 | and fast_yesterday >= slow_yesterday and fast_today < slow_today: 69 | # call方向:快线下穿慢线线形成死叉,做为卖出信号 70 | self.sell_tomorrow(order) 71 | elif order.expect_direction == -1 \ 72 | and slow_yesterday >= fast_yesterday and fast_today > slow_today: 73 | # put方向:快线上穿慢线做为卖出信号 74 | self.sell_tomorrow(order) 75 | -------------------------------------------------------------------------------- /abupy/FactorSellBu/ABuFactorSellNDay.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | """ 3 | 卖出择时示例因子:n日卖出策略,不管什么结果,买入后只持有N天 4 | """ 5 | 6 | from __future__ import absolute_import 7 | from __future__ import print_function 8 | from __future__ import division 9 | 10 | from .ABuFactorSellBase import AbuFactorSellBase, ESupportDirection 11 | 12 | __author__ = '阿布' 13 | __weixin__ = 'abu_quant' 14 | 15 | 16 | class AbuFactorSellNDay(AbuFactorSellBase): 17 | """n日卖出策略,不管交易现在什么结果,买入后只持有N天""" 18 | 19 | def _init_self(self, **kwargs): 20 | """kwargs中可以包含: 参数sell_n:代表买入后持有的天数,默认1天""" 21 | self.sell_n = kwargs.pop('sell_n', 1) 22 | self.is_sell_today = kwargs.pop('is_sell_today', False) 23 | self.sell_type_extra = '{}:sell_n={}'.format(self.__class__.__name__, self.sell_n) 24 | 25 | def support_direction(self): 26 | """因子支持两个方向""" 27 | return [ESupportDirection.DIRECTION_CAll.value, ESupportDirection.DIRECTION_PUT.value] 28 | 29 | def fit_day(self, today, orders): 30 | """ 31 | :param today: 当前驱动的交易日金融时间序列数据 32 | :param orders: 买入择时策略中生成的订单序列 33 | :return: 34 | """ 35 | for order in orders: 36 | # 将单子的持有天数进行增加 37 | order.keep_days += 1 38 | if order.keep_days >= self.sell_n: 39 | # 只要超过self.sell_n即卖出 40 | self.sell_today(order) if self.is_sell_today else self.sell_tomorrow(order) 41 | -------------------------------------------------------------------------------- /abupy/FactorSellBu/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from .ABuFactorSellBase import AbuFactorSellBase, AbuFactorSellXD, ESupportDirection 4 | from .ABuFactorPreAtrNStop import AbuFactorPreAtrNStop 5 | from .ABuFactorAtrNStop import AbuFactorAtrNStop 6 | from .ABuFactorCloseAtrNStop import AbuFactorCloseAtrNStop 7 | from .ABuFactorSellBreak import AbuFactorSellBreak 8 | from .ABuFactorSellNDay import AbuFactorSellNDay 9 | from .ABuFactorSellDM import AbuDoubleMaSell 10 | 11 | # noinspection all 12 | from . import ABuFS as fs 13 | 14 | __all__ = [ 15 | 'AbuFactorSellBase', 16 | 'AbuFactorSellXD', 17 | 'ESupportDirection', 18 | 'AbuFactorPreAtrNStop', 19 | 'AbuFactorAtrNStop', 20 | 'AbuFactorCloseAtrNStop', 21 | 'AbuFactorSellBreak', 22 | 'AbuFactorSellNDay', 23 | 'AbuDoubleMaSell', 24 | 'fs' 25 | ] 26 | -------------------------------------------------------------------------------- /abupy/IndicatorBu/ABuND.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from . import ABuNDAtr as atr 4 | from . import ABuNDBoll as boll 5 | from . import ABuNDMa as ma 6 | from . import ABuNDMacd as macd 7 | from . import ABuNDRsi as rsi 8 | 9 | __all__ = [ 10 | 'atr', 11 | 'boll', 12 | 'ma', 13 | 'macd', 14 | 'rsi' 15 | ] 16 | -------------------------------------------------------------------------------- /abupy/IndicatorBu/ABuNDBase.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | """ 3 | 技术指标工具基础模块 4 | """ 5 | 6 | from __future__ import absolute_import 7 | from __future__ import print_function 8 | from __future__ import division 9 | 10 | import logging 11 | 12 | import pandas as pd 13 | from enum import Enum 14 | 15 | from ..UtilBu import ABuDateUtil 16 | 17 | __author__ = '阿布' 18 | __weixin__ = 'abu_quant' 19 | 20 | 21 | class ECalcType(Enum): 22 | """ 23 | 技术指标技术方式类 24 | """ 25 | """使用talib透传技术指标计算""" 26 | E_FROM_TA = 0 27 | """使用pandas等库实现技术指标计算""" 28 | E_FROM_PD = 1 29 | 30 | 31 | # try: 32 | # # 不强制要求talib,全部局部引用 33 | # # noinspection PyUnresolvedReferences 34 | # import talib 35 | # g_calc_type = ECalcType.E_FROM_TA 36 | # except ImportError: 37 | # # 没有安装talib,使用E_FROM_PD 38 | # g_calc_type = ECalcType.E_FROM_PD 39 | """彻底不用talib,完全都使用自己计算的指标结果""" 40 | g_calc_type = ECalcType.E_FROM_PD 41 | 42 | 43 | def plot_from_order(plot_nd_func, order, date_ext, **kwargs): 44 | """ 45 | 封装在技术指标上绘制交易order信号通用流程 46 | :param plot_nd_func: 绘制技术指标的具体实现函数,必须callable 47 | :param order: AbuOrder对象转换的pd.DataFrame对象or pd.Series对象 48 | :param date_ext: int对象 eg. 如交易在2015-06-01执行,如date_ext=120,择start向前推120天,end向后推120天 49 | :param kwargs: plot_nd_func需要的其它关键字参数,直接透传给plot_nd_func 50 | """ 51 | if not callable(plot_nd_func): 52 | # plot_nd_func必须是callable 53 | raise TypeError('plot_nd_func must callable!!') 54 | 55 | if not isinstance(order, (pd.DataFrame, pd.Series)) and order.shape[0] > 0: 56 | # order必须是pd.DataFrame对象or pd.Series对象 且 单子数量要 > 0 57 | raise TypeError('order must DataFrame here!!') 58 | 59 | is_df = isinstance(order, pd.DataFrame) 60 | 61 | if is_df and order.shape[0] == 1: 62 | # 如果是只有1行pd.DataFrame对象则变成pd.Series 63 | is_df = False 64 | # 通过iloc即变成pd.Series对象 65 | # noinspection PyUnresolvedReferences 66 | order = order.iloc[0] 67 | 68 | def plot_from_series(p_order): 69 | """ 70 | 根据交易的symbol信息买入,卖出时间,以及date_ext完成通过ABuSymbolPd.make_kl_df获取金融时间序列, 71 | 在成功获取数据后使用plot_nd_func完成买入卖出信号绘制及对应的技术指标绘制 72 | :param p_order: AbuOrder对象转换的pd.Series对象 73 | """ 74 | # 确定交易对象 75 | target_symbol = p_order['symbol'] 76 | # 单子都必须有买入时间 77 | buy_index = pd.to_datetime(str(p_order['buy_date'])) 78 | sell_index = None 79 | 80 | start = ABuDateUtil.fmt_date(p_order['buy_date']) 81 | # 通过date_ext确定start,即买人单子向前推date_ext天 82 | start = ABuDateUtil.begin_date(date_ext, date_str=start, fix=False) 83 | if p_order['sell_type'] != 'keep': 84 | sell_index = pd.to_datetime(str(p_order['sell_date'])) 85 | # 如果有卖出,继续通过sell_date,date_ext确定end时间 86 | end = ABuDateUtil.fmt_date(p_order['sell_date']) 87 | # -date_ext 向前 88 | end = ABuDateUtil.begin_date(-date_ext, date_str=end, fix=False) 89 | else: 90 | end = None 91 | from ..MarketBu import ABuSymbolPd 92 | # 组织好参数,确定了请求范围后开始获取金融时间序列数据 93 | kl_pd = ABuSymbolPd.make_kl_df(target_symbol, start=start, end=end) 94 | if kl_pd is None or kl_pd.shape[0] == 0: 95 | logging.debug(target_symbol + ': has net error in data') 96 | return 97 | # 使用plot_nd_func完成买入卖出信号绘制及对应的技术指标绘制 98 | return plot_nd_func(kl_pd, with_points=buy_index, with_points_ext=sell_index, **kwargs) 99 | 100 | if not is_df: 101 | return plot_from_series(order) 102 | else: 103 | # 多个order, apply迭代执行plot_from_series 104 | order = order[order['result'] != 0] 105 | return order.apply(plot_from_series, axis=1) 106 | -------------------------------------------------------------------------------- /abupy/IndicatorBu/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from . import ABuND as nd 4 | 5 | __all__ = [ 6 | 'nd' 7 | ] 8 | -------------------------------------------------------------------------------- /abupy/MLBu/ABuMLApi.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | # noinspection PyUnresolvedReferences 4 | from .ABuMLBinsCs import * 5 | # noinspection PyUnresolvedReferences 6 | from .ABuMLExecute import * 7 | # noinspection PyUnresolvedReferences 8 | from .ABuMLGrid import * 9 | # noinspection PyUnresolvedReferences 10 | from .ABuML import EMLFitType 11 | # noinspection PyUnresolvedReferences 12 | from .ABuMLPd import BtcBigWaveClf, ClosePredict 13 | -------------------------------------------------------------------------------- /abupy/MLBu/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from .ABuML import AbuML 4 | from .ABuMLCreater import AbuMLCreater 5 | from .ABuMLPd import AbuMLPd 6 | from . import ABuMLExecute 7 | from . import ABuMLGrid 8 | 9 | from . import ABuMLApi as ml 10 | 11 | __all__ = [ 12 | 'AbuML', 13 | 'AbuMLCreater', 14 | 'AbuMLPd', 15 | 'ABuMLExecute', 16 | 'ABuMLGrid', 17 | 18 | 'ml' 19 | ] 20 | -------------------------------------------------------------------------------- /abupy/MarketBu/ABuHkUnit.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """ 3 | 港股每一手交易数量模块 4 | """ 5 | 6 | from __future__ import print_function 7 | from __future__ import absolute_import 8 | from __future__ import division 9 | 10 | import os 11 | 12 | import pandas as pd 13 | 14 | from ..CoreBu.ABuBase import FreezeAttrMixin 15 | from ..CoreBu import ABuEnv 16 | from ..CoreBu.ABuFixes import six 17 | from ..UtilBu.ABuDTUtil import singleton 18 | from ..MarketBu.ABuSymbol import Symbol 19 | 20 | __author__ = '阿布' 21 | __weixin__ = 'abu_quant' 22 | 23 | _rom_dir = ABuEnv.g_project_rom_data_dir 24 | """文件定期重新爬取,更新""" 25 | _hk_unit_csv = os.path.join(_rom_dir, 'hk_unit.csv') 26 | """默认每一手股数1000""" 27 | K_DEFAULT_UNIT = 1000 28 | 29 | 30 | @singleton 31 | class AbuHkUnit(FreezeAttrMixin): 32 | """AbuHkUnit单例,混入FreezeAttrMixin在__init__中冻结了接口,外部只可以读取""" 33 | 34 | def __init__(self): 35 | """ 36 | self.hk_unit_df表结构如下所示:只有一个列unit代表每一手股数,行代表港股symbol 37 | unit 38 | hk02011 2000 39 | hk01396 2000 40 | hk08112 4800 41 | hk08198 4000 42 | hk01143 4000 43 | ............ 44 | """ 45 | # 读取本地csv到内存,由于AbuHkUnit单例只进行一次 46 | self.hk_unit_df = pd.read_csv(_hk_unit_csv, index_col=0) 47 | # __init__中使用FreezeAttrMixin._freeze冻结了接口 48 | self._freeze() 49 | 50 | def query_unit(self, symbol): 51 | """ 52 | 对外查询接口,查询对应symbol每一手交易数量 53 | :param symbol: 可以是Symbol对象,也可以是symbol字符串对象 54 | """ 55 | if isinstance(symbol, Symbol): 56 | # Symbol对象进行转换 57 | symbol = symbol.value 58 | elif isinstance(symbol, six.string_types) and symbol.isdigit(): 59 | # symbol字符串, 但是没有hk,则加上 60 | symbol = 'hk{}'.format(symbol) 61 | 62 | # noinspection PyBroadException 63 | try: 64 | unit = self.hk_unit_df.loc[symbol].values[0] 65 | except: 66 | # 查询失败赋予默认值 67 | unit = K_DEFAULT_UNIT 68 | return unit 69 | 70 | def __str__(self): 71 | """打印对象显示:hk_unit_df.info, hk_unit_df.describe""" 72 | return 'info:\n{}\ndescribe:\n{}'.format(self.hk_unit_df.info(), 73 | self.hk_unit_df.describe()) 74 | 75 | __repr__ = __str__ 76 | 77 | def __len__(self): 78 | """对象长度:hk_unit_df.shape[0],即行数""" 79 | return self.hk_unit_df.shape[0] 80 | 81 | def __contains__(self, item): 82 | """ 83 | 成员测试:标准化item后检测item是否在self.hk_unit_df.index中 84 | :param item: 可以是Symbol对象,也可以是symbol字符串对象 85 | """ 86 | if isinstance(item, Symbol): 87 | item = item.value 88 | elif isinstance(item, six.string_types) and item.isdigit(): 89 | item = 'hk{}'.format(item) 90 | 91 | return item in self.hk_unit_df.index 92 | 93 | def __getitem__(self, key): 94 | """索引获取:套接self.query_unit(key)""" 95 | return self.query_unit(key) 96 | 97 | def __setitem__(self, key, value): 98 | """索引设置:对外抛出错误, 即不准许外部设置""" 99 | raise AttributeError("AbuHkUnit set value!!!") 100 | 101 | 102 | """由于封装对外所以不使用模块单例""" 103 | # """模块单例""" 104 | # single_hk_unit = AbuHkUnit() 105 | -------------------------------------------------------------------------------- /abupy/MarketBu/ABuNetWork.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | """ 3 | 网络统一接口模块 4 | """ 5 | 6 | from __future__ import print_function 7 | from __future__ import absolute_import 8 | from __future__ import division 9 | 10 | import logging 11 | import requests 12 | import time 13 | import ast 14 | 15 | from requests.packages.urllib3.exceptions import ReadTimeoutError 16 | 17 | """g_enable_lru_cache针对lru_cache是否开启,考虑到目前爬取的数据fetch url都会有时间戳等可变字段,所以默认关闭""" 18 | g_enable_lru_cache = False 19 | g_lru_cache_max = 300 20 | if g_enable_lru_cache: 21 | # 开启import lru_cache 22 | from ..CoreBu.ABuFixes import lru_cache 23 | else: 24 | # 导入一个空的装饰器as lru_cache 25 | from ..UtilBu.ABuDTUtil import empty_wrapper_with_params as lru_cache 26 | # 设置requests库的日志级别 27 | logging.getLogger("requests").setLevel(logging.WARNING) 28 | 29 | 30 | @lru_cache(maxsize=g_lru_cache_max) 31 | def get(url, params=None, headers=None, retry=3, **kwargs): 32 | """ 33 | :param url: 请求base url 34 | :param params: url params参数 35 | :param headers: http head头信息 36 | :param retry: 重试次数,默认retry=3 37 | :param kwargs: 透传给requests.get,可设置ua等,超时等参数 38 | """ 39 | req_count = 0 40 | while req_count < retry: 41 | # 重试retry次 42 | try: 43 | resp = requests.get(url=url, params=params, headers=headers, **kwargs) 44 | if resp.status_code == 200 or resp.status_code == 206: 45 | # 如果200,206返回,否则继续走重试 46 | return resp 47 | except ReadTimeoutError: 48 | # 超时直接重试就行,不打日志 49 | pass 50 | except Exception as e: 51 | logging.exception(e) 52 | req_count += 1 53 | time.sleep(0.5) 54 | continue 55 | return None 56 | 57 | 58 | def post(url, params=None, headers=None, retry=3, **kwargs): 59 | """ 60 | :param url: 请求base url 61 | :param params: url params参数 62 | :param headers: http head头信息 63 | :param retry: 重试次数,默认retry=3 64 | :param kwargs: 透传给requests.get,可设置ua等,超时等参数 65 | """ 66 | req_count = 0 67 | while req_count < retry: 68 | try: 69 | resp = requests.post(url=url, params=params, headers=headers, **kwargs) 70 | return resp 71 | except Exception as e: 72 | logging.exception(e) 73 | req_count += 1 74 | time.sleep(0.5) 75 | continue 76 | return None 77 | 78 | 79 | def ast_parse_js(js_var): 80 | """ 81 | 通过ast模块解析Javascript字符串 82 | :param js_var: Javascript字符串 83 | :return: map, dict or value 84 | """ 85 | js_mode = ast.parse(js_var) 86 | body_head = js_mode.body[0] 87 | 88 | def _parse(node): 89 | if isinstance(node, ast.Expr): 90 | return _parse(node.value) 91 | elif isinstance(node, ast.Num): 92 | return node.n 93 | elif isinstance(node, ast.Str): 94 | return node.s 95 | elif isinstance(node, ast.Name): 96 | return node.id 97 | elif isinstance(node, ast.Dict): 98 | return dict(zip(map(_parse, node.keys), map(_parse, node.values))) 99 | elif isinstance(node, ast.List): 100 | return map(_parse, node.elts) 101 | else: 102 | raise NotImplementedError(node.__class__) 103 | 104 | return _parse(body_head) 105 | 106 | 107 | def parse_js(js_var): 108 | """ 109 | 通过eval解析Javascript字符串 110 | :param js_var: Javascript字符串 111 | :return: dict 112 | """ 113 | obj = eval(js_var, type('Dummy', (dict,), dict(__getitem__=lambda s, n: n))()) 114 | return obj 115 | -------------------------------------------------------------------------------- /abupy/MarketBu/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from .ABuDataBase import BaseMarket, FuturesBaseMarket, StockBaseMarket, TCBaseMarket, SupportMixin 4 | from .ABuDataParser import AbuDataParseWrap 5 | from . import ABuSymbolPd 6 | from .ABuSymbolPd import get_price 7 | from .ABuSymbol import IndexSymbol, Symbol, code_to_symbol, search_to_symbol_dict 8 | from . import ABuSymbol 9 | from ..MarketBu.ABuSymbolStock import AbuSymbolCN, AbuSymbolUS, AbuSymbolHK, query_stock_info 10 | from .ABuSymbolFutures import AbuFuturesCn, AbuFuturesGB 11 | from .ABuHkUnit import AbuHkUnit 12 | from . import ABuMarket 13 | from .ABuMarket import MarketMixin 14 | from . import ABuIndustries 15 | from . import ABuMarketDrawing 16 | from . import ABuNetWork 17 | 18 | __all__ = [ 19 | 'BaseMarket', 20 | 'FuturesBaseMarket', 21 | 'StockBaseMarket', 22 | 'TCBaseMarket', 23 | 'SupportMixin', 24 | 'AbuDataParseWrap', 25 | 'MarketMixin', 26 | 'ABuSymbolPd', 27 | 'get_price', 28 | 'ABuSymbol', 29 | 'AbuSymbolCN', 30 | 'AbuFuturesGB', 31 | 'AbuSymbolUS', 32 | 'AbuSymbolHK', 33 | 'query_stock_info', 34 | 'AbuFuturesCn', 35 | 'AbuHkUnit', 36 | 'ABuMarket', 37 | 'IndexSymbol', 38 | 'Symbol', 39 | 'code_to_symbol', 40 | 'search_to_symbol_dict', 41 | 'ABuIndustries', 42 | 'ABuMarketDrawing', 43 | 'ABuNetWork' 44 | ] 45 | -------------------------------------------------------------------------------- /abupy/MetricsBu/ABuMetrics.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | -------------------------------------------------------------------------------- /abupy/MetricsBu/ABuMetricsFutures.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | """期货度量模块""" 3 | from __future__ import absolute_import 4 | from __future__ import division 5 | from __future__ import print_function 6 | 7 | import matplotlib.pyplot as plt 8 | import numpy as np 9 | import seaborn as sns 10 | 11 | from ..CoreBu import ABuEnv 12 | from ..ExtBu.empyrical import stats 13 | from ..MetricsBu.ABuMetricsBase import AbuMetricsBase, valid_check 14 | from ..UtilBu.ABuDTUtil import warnings_filter 15 | 16 | __author__ = '阿布' 17 | __weixin__ = 'abu_quant' 18 | 19 | 20 | class AbuMetricsFutures(AbuMetricsBase): 21 | """期货度量类,主要区别在于不涉及benchmark""" 22 | 23 | def _metrics_base_stats(self): 24 | """度量真实成交了的capital_pd,即涉及资金的度量,期货相关不涉及benchmark""" 25 | # 平均资金利用率 26 | self.cash_utilization = 1 - (self.capital.capital_pd.cash_blance / 27 | self.capital.capital_pd.capital_blance).mean() 28 | self.algorithm_returns = np.round(self.capital.capital_pd['capital_blance'].pct_change(), 3) 29 | 30 | # 收益cum数据 31 | # noinspection PyTypeChecker 32 | self.algorithm_cum_returns = stats.cum_returns(self.algorithm_returns) 33 | 34 | # 最后一日的cum return 35 | self.algorithm_period_returns = self.algorithm_cum_returns[-1] 36 | 37 | # 交易天数 38 | self.num_trading_days = len(self.algorithm_cum_returns) 39 | 40 | # 年化收益 41 | self.algorithm_annualized_returns = \ 42 | (ABuEnv.g_market_trade_year / self.num_trading_days) * self.algorithm_period_returns 43 | 44 | # noinspection PyUnresolvedReferences 45 | self.mean_algorithm_returns = self.algorithm_returns.cumsum() / np.arange(1, self.num_trading_days + 1, 46 | dtype=np.float64) 47 | # noinspection PyTypeChecker 48 | self.algorithm_volatility = stats.annual_volatility(self.algorithm_returns) 49 | # noinspection PyTypeChecker 50 | self.algorithm_sharpe = stats.sharpe_ratio(self.algorithm_returns) 51 | # 最大回撤 52 | # noinspection PyUnresolvedReferences 53 | self.max_drawdown = stats.max_drawdown(self.algorithm_returns.values) 54 | 55 | @valid_check 56 | @warnings_filter # skip: statsmodels / nonparametric / kdetools.py:20 57 | def plot_returns_cmp(self, only_show_returns=False, only_info=False): 58 | """考虑资金情况下的度量,进行与benchmark的收益度量对比,收益趋势,资金变动可视化,以及其它度量信息,不涉及benchmark""" 59 | 60 | self.log_func('买入后卖出的交易数量:{}'.format(self.order_has_ret.shape[0])) 61 | self.log_func('胜率:{:.4f}%'.format(self.win_rate * 100)) 62 | 63 | self.log_func('平均获利期望:{:.4f}%'.format(self.gains_mean * 100)) 64 | self.log_func('平均亏损期望:{:.4f}%'.format(self.losses_mean * 100)) 65 | 66 | self.log_func('盈亏比:{:.4f}'.format(self.win_loss_profit_rate)) 67 | 68 | self.log_func('策略收益: {:.4f}%'.format(self.algorithm_period_returns * 100)) 69 | self.log_func('策略年化收益: {:.4f}%'.format(self.algorithm_annualized_returns * 100)) 70 | 71 | self.log_func('策略买入成交比例:{:.4f}%'.format(self.buy_deal_rate * 100)) 72 | self.log_func('策略资金利用率比例:{:.4f}%'.format(self.cash_utilization * 100)) 73 | self.log_func('策略共执行{}个交易日'.format(self.num_trading_days)) 74 | 75 | if only_info: 76 | return 77 | 78 | self.algorithm_cum_returns.plot() 79 | plt.legend(['algorithm returns'], loc='best') 80 | plt.show() 81 | 82 | if only_show_returns: 83 | return 84 | sns.regplot(x=np.arange(0, len(self.algorithm_cum_returns)), y=self.algorithm_cum_returns.values) 85 | plt.show() 86 | sns.distplot(self.capital.capital_pd['capital_blance'], kde_kws={"lw": 3, "label": "capital blance kde"}) 87 | plt.show() 88 | 89 | @valid_check 90 | def plot_sharp_volatility_cmp(self, only_info=False): 91 | """sharp,volatility信息输出""" 92 | 93 | self.log_func('策略Sharpe夏普比率: {:.4f}'.format(self.algorithm_sharpe)) 94 | self.log_func('策略波动率Volatility: {:.4f}'.format(self.algorithm_volatility)) 95 | -------------------------------------------------------------------------------- /abupy/MetricsBu/ABuMetricsTC.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | """比特币度量模块""" 3 | 4 | from __future__ import absolute_import 5 | from __future__ import division 6 | from __future__ import print_function 7 | 8 | 9 | from ..MetricsBu.ABuMetricsFutures import AbuMetricsFutures 10 | 11 | __author__ = '阿布' 12 | __weixin__ = 'abu_quant' 13 | 14 | 15 | class AbuMetricsTC(AbuMetricsFutures): 16 | """比特币,莱特币等币类型度量,自扩张使用,暂时继承AbuMetricsFutures,即不涉及benchmark,user可继承扩展需求""" 17 | -------------------------------------------------------------------------------- /abupy/MetricsBu/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from .ABuGridSearch import ParameterGrid, GridSearch 4 | from .ABuCrossVal import AbuCrossVal 5 | from .ABuMetricsBase import AbuMetricsBase, MetricsDemo 6 | from .ABuMetricsFutures import AbuMetricsFutures 7 | from .ABuMetricsTC import AbuMetricsTC 8 | from .ABuMetricsScore import AbuBaseScorer, WrsmScorer, AbuScoreTuple, make_scorer 9 | 10 | from . import ABuGridHelper 11 | from . import ABuMetrics as metrics 12 | 13 | __all__ = [ 14 | 'ParameterGrid', 15 | 'GridSearch', 16 | 'AbuCrossVal', 17 | 'AbuMetricsBase', 18 | 'AbuMetricsFutures', 19 | 'AbuMetricsTC', 20 | 'MetricsDemo', 21 | 'AbuBaseScorer', 22 | 'WrsmScorer', 23 | 'make_scorer', 24 | 'ABuGridHelper', 25 | 'metrics'] 26 | -------------------------------------------------------------------------------- /abupy/PickStockBu/ABuPickRegressAngMinMax.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | """ 3 | 选股示例因子:价格拟合角度选股因子 4 | """ 5 | from __future__ import print_function 6 | from __future__ import absolute_import 7 | from __future__ import division 8 | 9 | import numpy as np 10 | 11 | from ..UtilBu import ABuRegUtil 12 | from .ABuPickStockBase import AbuPickStockBase, reversed_result 13 | 14 | __author__ = '阿布' 15 | __weixin__ = 'abu_quant' 16 | 17 | 18 | class AbuPickRegressAngMinMax(AbuPickStockBase): 19 | """拟合角度选股因子示例类""" 20 | def _init_self(self, **kwargs): 21 | """通过kwargs设置拟合角度边际条件,配置因子参数""" 22 | 23 | # 暂时与base保持一致不使用kwargs.pop('a', default)方式 24 | # fit_pick中 ang > threshold_ang_min, 默认负无穷,即默认所有都符合 25 | self.threshold_ang_min = -np.inf 26 | if 'threshold_ang_min' in kwargs: 27 | # 设置最小角度阀值 28 | self.threshold_ang_min = kwargs['threshold_ang_min'] 29 | 30 | # fit_pick中 ang < threshold_ang_max, 默认正无穷,即默认所有都符合 31 | self.threshold_ang_max = np.inf 32 | if 'threshold_ang_max' in kwargs: 33 | # 设置最大角度阀值 34 | self.threshold_ang_max = kwargs['threshold_ang_max'] 35 | 36 | @reversed_result 37 | def fit_pick(self, kl_pd, target_symbol): 38 | """开始根据自定义拟合角度边际参数进行选股""" 39 | 40 | # 计算走势角度 41 | ang = ABuRegUtil.calc_regress_deg(kl_pd.close, show=False) 42 | # 根据参数进行角度条件判断 43 | if self.threshold_ang_min < ang < self.threshold_ang_max: 44 | return True 45 | return False 46 | 47 | def fit_first_choice(self, pick_worker, choice_symbols, *args, **kwargs): 48 | raise NotImplementedError('AbuPickRegressAng fit_first_choice unsupported now!') 49 | -------------------------------------------------------------------------------- /abupy/PickStockBu/ABuPickSimilarNTop.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | """ 3 | 选股示例因子:相似度选股因子,主要示例fit_first_choice 4 | """ 5 | 6 | from __future__ import print_function 7 | from __future__ import absolute_import 8 | from __future__ import division 9 | 10 | import numpy as np 11 | 12 | from ..UtilBu import ABuDateUtil 13 | from ..TLineBu import ABuTLSimilar 14 | from .ABuPickStockBase import AbuPickStockBase, reversed_result 15 | from ..SimilarBu.ABuSimilar import find_similar_with_se, ECoreCorrType 16 | 17 | """外部可通过如:abupy.ps.similar_top = 300修改默认值""" 18 | g_pick_similar_n_top = 100 19 | 20 | 21 | # noinspection PyAttributeOutsideInit 22 | class AbuPickSimilarNTop(AbuPickStockBase): 23 | """相似度选股因子示例类""" 24 | 25 | def _init_self(self, **kwargs): 26 | """通过kwargs设置相似度选股边际条件,相似度计算方法,返回目标数量等,配置因子参数""" 27 | 28 | # 暂时与base保持一致不使用kwargs.pop('a', default)方式 29 | # 设置目标相似度交易对象 30 | self.similar_stock = kwargs['similar_stock'] 31 | 32 | # 设置目标相似度选取top个数,只在fit_first_choice中使用,默认top100, 即前100个最相似的股票 33 | self.n_top = g_pick_similar_n_top 34 | if 'n_top' in kwargs: 35 | self.n_top = kwargs['n_top'] 36 | 37 | # 设置fit_pick中使用的最小相似边际条件 38 | self.threshold_similar_min = -np.inf 39 | if 'threshold_similar_min' in kwargs: 40 | self.threshold_similar_min = kwargs['threshold_similar_min'] 41 | 42 | # 设置fit_pick中使用的最大相似边际条件 43 | self.threshold_similar_max = np.inf 44 | if 'threshold_similar_max' in kwargs: 45 | self.threshold_similar_max = kwargs['threshold_similar_max'] 46 | 47 | # 相似度是否使用时间加权计算,如果使用速度会慢 48 | self.rolling = False 49 | if 'rolling' in kwargs: 50 | self.rolling = kwargs['rolling'] 51 | 52 | # 相似度计算使用算法设置 53 | self.corr_type = ECoreCorrType.E_CORE_TYPE_PEARS 54 | if 'corr_type' in kwargs: 55 | self.corr_type = kwargs['corr_type'] 56 | # 相似度rank缓存 57 | self.s_sum_rank = None 58 | 59 | @reversed_result 60 | def fit_pick(self, kl_pd, target_symbol): 61 | """开始根据自定义相似度边际条件进行选股""" 62 | 63 | # 由于外层worker需要不断迭代symbol使用同一个因子对象进行选股,所以这里缓存了相似度rank结果,只计算一次 64 | similar_rank, self.s_sum_rank = ABuTLSimilar.calc_similar(self.similar_stock, target_symbol, 65 | self.s_sum_rank, 66 | show=False) 67 | # 边际筛选 68 | if self.threshold_similar_min < similar_rank < self.threshold_similar_max: 69 | return True 70 | return False 71 | 72 | def fit_first_choice(self, pick_worker, choice_symbols, *args, **kwargs): 73 | """ 74 | 因子相似度批量选股接口 75 | :param pick_worker: 选股worker,AbuPickStockWorker实例对象 76 | :param choice_symbols: 初始备选交易对象序列 77 | :return: 78 | """ 79 | 80 | # 获取交易目标选股阶段的金融时间序列 81 | similar_kl_pd = pick_worker.kl_pd_manager.get_pick_stock_kl_pd(self.similar_stock, self.xd, self.min_xd) 82 | if similar_kl_pd is None or len(similar_kl_pd) == 0: 83 | return [] 84 | 85 | # 选股阶段的金融时间序列最后一个日期作为similar_end 86 | similar_end = ABuDateUtil.timestamp_to_str(similar_kl_pd.index[-1]) 87 | # 选股阶段的金融时间序列第一个个日期作为similar_start 88 | similar_start = ABuDateUtil.timestamp_to_str(similar_kl_pd.index[0]) 89 | # 通过ABuSimilar模块中的find_similar_with_se计算与交易目标的相似度rank dict 90 | net_cg_ret = find_similar_with_se(self.similar_stock, similar_start, similar_end, 91 | rolling=self.rolling, show=False, 92 | corr_type=self.corr_type) 93 | # 取相似度结果的n_top个,作为选股结果 94 | similar_top_choice = [ss[0] for ss in net_cg_ret[1:self.n_top + 1]] 95 | # 通过集合选取在初始备选交易对象序列和相似度选股序列中的子序列 96 | return list(set(similar_top_choice) & set(choice_symbols)) 97 | -------------------------------------------------------------------------------- /abupy/PickStockBu/ABuPickStock.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | # noinspection all 4 | from . import ABuPickSimilarNTop as similar_top 5 | # noinspection PyUnresolvedReferences 6 | from .ABuPickStockBase import reversed_result 7 | -------------------------------------------------------------------------------- /abupy/PickStockBu/ABuPickStockBase.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | """ 3 | 选股因子抽象基类 4 | """ 5 | 6 | from __future__ import print_function 7 | from __future__ import absolute_import 8 | from __future__ import division 9 | 10 | import functools 11 | from abc import ABCMeta, abstractmethod 12 | 13 | from ..CoreBu.ABuFixes import six 14 | from ..CoreBu import ABuEnv 15 | from ..CoreBu.ABuBase import AbuParamBase 16 | 17 | __author__ = '阿布' 18 | __weixin__ = 'abu_quant' 19 | 20 | 21 | def reversed_result(func): 22 | """对选股结果进行反转的装饰器,装饰在fit_pick上""" 23 | @functools.wraps(func) 24 | def wrapper(self, *args, **kwargs): 25 | result = func(self, *args, **kwargs) 26 | # 通过对象变量reversed,判断是否反转结果 27 | result = not result if self.reversed else result 28 | return result 29 | 30 | return wrapper 31 | 32 | 33 | class AbuPickStockBase(six.with_metaclass(ABCMeta, AbuParamBase)): 34 | def __init__(self, capital, benchmark, **kwargs): 35 | """ 36 | :param capital:资金类AbuCapital实例化对象 37 | :param benchmark:交易基准对象,AbuBenchmark实例对象 38 | :param kwargs:其它可扩展参数 39 | """ 40 | self.capital = capital 41 | self.benchmark = benchmark 42 | 43 | # 所有自定义参数不使用kwargs.pop('a', default)方式,因为有从配置文件读取等需求,而且后续_init_self可能也还需要 44 | # 默认反转结果false,通过kwargs参数控制 45 | self.reversed = False 46 | if 'reversed' in kwargs: 47 | self.reversed = kwargs['reversed'] 48 | 49 | # 默认选股周期默认一年的交易日 50 | self.xd = ABuEnv.g_market_trade_year 51 | if 'xd' in kwargs: 52 | self.xd = kwargs['xd'] 53 | 54 | # 最小选股周期,小于这个将抛弃,即结果投反对票 55 | self.min_xd = int(self.xd / 2) 56 | if 'min_xd' in kwargs: 57 | self.min_xd = kwargs['min_xd'] 58 | 59 | # 因子独有的init继续 60 | self._init_self(**kwargs) 61 | 62 | def __str__(self): 63 | """打印对象显示:class name, benchmark, reversed, xd, min_xd""" 64 | return '{}: {}, reversed:{}, xd:{}, min_xd:{}'.format(self.__class__.__name__, 65 | self.benchmark, self.reversed, self.xd, self.min_xd) 66 | 67 | __repr__ = __str__ 68 | 69 | @abstractmethod 70 | def _init_self(self, **kwargs): 71 | """子类因子针对可扩展参数的初始化""" 72 | pass 73 | 74 | @abstractmethod 75 | def fit_pick(self, *args, **kwargs): 76 | """选股操作接口,即因子对象针对一个交易目标的投票结果,具体详见示例因子""" 77 | pass 78 | 79 | @abstractmethod 80 | def fit_first_choice(self, pick_worker, choice_symbols, *args, **kwargs): 81 | """因子首选批量选股接口,即因子对象对多个交易目标的投票结果,具体详见示例因子""" 82 | pass 83 | -------------------------------------------------------------------------------- /abupy/PickStockBu/ABuPickStockPriceMinMax.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | """ 3 | 选股示例因子:价格选股因子 4 | """ 5 | from __future__ import print_function 6 | from __future__ import absolute_import 7 | from __future__ import division 8 | 9 | from .ABuPickStockBase import AbuPickStockBase, reversed_result 10 | import numpy as np 11 | 12 | __author__ = '阿布' 13 | __weixin__ = 'abu_quant' 14 | 15 | 16 | class AbuPickStockPriceMinMax(AbuPickStockBase): 17 | """价格选股因子示例类""" 18 | def _init_self(self, **kwargs): 19 | """通过kwargs设置选股价格边际条件,配置因子参数""" 20 | 21 | # 暂时与base保持一致不使用kwargs.pop('a', default)方式 22 | # fit_pick中选择 > 最小(threshold_price_min), 默认负无穷,即默认所有都符合 23 | self.threshold_price_min = -np.inf 24 | if 'threshold_price_min' in kwargs: 25 | # 最小价格阀值 26 | self.threshold_price_min = kwargs['threshold_price_min'] 27 | 28 | # fit_pick中选择 < 最大(threshold_price_max), 默认正无穷,即默认所有都符合 29 | self.threshold_price_max = np.inf 30 | if 'threshold_price_max' in kwargs: 31 | # 最大价格阀值 32 | self.threshold_price_max = kwargs['threshold_price_max'] 33 | 34 | @reversed_result 35 | def fit_pick(self, kl_pd, target_symbol): 36 | """开始根据自定义价格边际参数进行选股""" 37 | if kl_pd.close.max() < self.threshold_price_max and kl_pd.close.min() > self.threshold_price_min: 38 | # kl_pd.close的最大价格 < 最大价格阀值 且 kl_pd.close的最小价格 > 最小价格阀值 39 | return True 40 | return False 41 | 42 | def fit_first_choice(self, pick_worker, choice_symbols, *args, **kwargs): 43 | raise NotImplementedError('AbuPickStockPriceMinMax fit_first_choice unsupported now!') 44 | -------------------------------------------------------------------------------- /abupy/PickStockBu/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from .ABuPickRegressAngMinMax import AbuPickRegressAngMinMax 4 | from .ABuPickSimilarNTop import AbuPickSimilarNTop 5 | from .ABuPickStockBase import AbuPickStockBase 6 | from .ABuPickStockPriceMinMax import AbuPickStockPriceMinMax 7 | from .ABuPickStockDemo import AbuPickStockShiftDistance, AbuPickStockNTop 8 | from . import ABuPickStock as ps 9 | 10 | __all__ = [ 11 | 'AbuPickRegressAngMinMax', 12 | 'AbuPickSimilarNTop', 13 | 'AbuPickStockBase', 14 | 'AbuPickStockPriceMinMax', 15 | 'AbuPickStockShiftDistance', 16 | 'AbuPickStockNTop', 17 | 'ps'] 18 | -------------------------------------------------------------------------------- /abupy/RomDataBu/csv.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/abupy/RomDataBu/csv.zip -------------------------------------------------------------------------------- /abupy/RomDataBu/futures_cn.csv: -------------------------------------------------------------------------------- 1 | ,symbol,product,min_deposit,min_unit,commission,exchange 2 | 0,V0,PVC,0.07,5,2,DCE 3 | 1,P0,棕榈,0.07,10,2.5,DCE 4 | 2,B0,豆二,0.05,10,2,DCE 5 | 3,M0,豆粕,0.07,10,1.5,DCE 6 | 4,I0,铁矿石,0.1,100,8,DCE 7 | 5,JD0,鸡蛋,0.08,5,6,DCE 8 | 6,L0,塑料,0.07,5,2,DCE 9 | 7,PP0,PP,0.07,5,4,DCE 10 | 8,FB0,纤维板,0.2,500,10,DCE 11 | 9,BB0,胶合板,0.2,500,10,DCE 12 | 10,Y0,豆油,0.07,10,2.5,DCE 13 | 11,C0,玉米,0.07,10,1.2,DCE 14 | 12,A0,豆一,0.07,10,2,DCE 15 | 13,J0,焦炭,0.15,100,8,DCE 16 | 14,JM0,焦煤,0.15,60,8,DCE 17 | 15,CS0,玉米淀粉,0.07,10,1.5,DCE 18 | 16,TA0,PTA,0.06,5,3,ZZCE 19 | 17,OI0,菜油,0.07,5,2.5,ZZCE 20 | 18,RS0,菜籽,0.2,10,2,ZZCE 21 | 19,RM0,菜粕,0.06,10,3,ZZCE 22 | 20,ZC0,动力煤,0.08,200,6,ZZCE 23 | 21,WH0,强麦,0.05,10,2.5,ZZCE 24 | 22,JR0,粳稻,0.05,20,3,ZZCE 25 | 23,SR0,白糖,0.05,10,3,ZZCE 26 | 24,CF0,棉花,0.07,5,6,ZZCE 27 | 25,RI0,早籼稻,0.05,10,2.5,ZZCE 28 | 26,MA0,郑醇,0.07,10,2,ZZCE 29 | 27,FG0,玻璃,0.07,20,3,ZZCE 30 | 28,LR0,晚籼稻,0.05,20,3,ZZCE 31 | 29,SF0,硅铁,0.07,5,3,ZZCE 32 | 30,SM0,锰硅,0.07,5,3,ZZCE 33 | 31,FU0,燃油,0.2,50,10,SHFE 34 | 32,AL0,沪铝,0.09,5,3,SHFE 35 | 33,RU0,橡胶,0.12,10,10,SHFE 36 | 34,ZN0,沪锌,0.09,5,3,SHFE 37 | 35,CU0,沪铜,0.09,5,8,SHFE 38 | 36,AU0,黄金,0.06,1000,10,SHFE 39 | 37,RB0,螺纹钢,0.11,10,10,SHFE 40 | 38,WR0,线材,0.2,10,8,SHFE 41 | 39,PB0,沪铅,0.09,25,8,SHFE 42 | 40,AG0,白银,0.08,15,10,SHFE 43 | 41,BU0,沥青,0.09,10,10,SHFE 44 | 42,HC0,热轧卷板,0.09,10,10,SHFE 45 | 43,SN0,沪锡,0.09,1,3,SHFE 46 | 44,NI0,沪镍,0.1,1,6,SHFE 47 | -------------------------------------------------------------------------------- /abupy/RomDataBu/futures_gb.csv: -------------------------------------------------------------------------------- 1 | ,symbol,product,min_deposit,min_unit,exchange 2 | 0,NID,伦敦镍,0.07,6,LME 3 | 1,PBD,伦敦铅,0.1,25,LME 4 | 2,SND,伦敦锡,0.05,5,LME 5 | 3,ZSD,伦敦锌,0.1,25,LME 6 | 4,AHD,伦敦铝,0.08,25,LME 7 | 5,CAD,伦敦铜,0.08,25,LME 8 | 6,XAU,伦敦金,0.1,1,LME 9 | 7,XAG,伦敦银,0.1,100,LME 10 | 8,XPT,伦敦铂金,0.1,1,LME 11 | 9,S,美黄豆,0.1,5000,CBOT 12 | 10,W,美小麦,0.1,5000,CBOT 13 | 11,C,美玉米,0.1,5000,CBOT 14 | 12,BO,美豆油,0.1,60000,CBOT 15 | 13,SM,美豆粕,0.1,100,CBOT 16 | 14,HG,纽约铜,0.1,25000,NYMEX 17 | 15,SI,纽约白银,0.08,5000,NYMEX 18 | 16,GC,纽约黄金,0.08,100,NYMEX 19 | 17,CL,纽约原油,0.07,1000,NYMEX 20 | 18,NG,纽约天然气,0.07,10000,NYMEX 21 | -------------------------------------------------------------------------------- /abupy/RomDataBu/hq_nav.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/abupy/RomDataBu/hq_nav.txt -------------------------------------------------------------------------------- /abupy/RomDataBu/symbols_db.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/abupy/RomDataBu/symbols_db.db -------------------------------------------------------------------------------- /abupy/SimilarBu/ABuSimilarCache.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | from __future__ import absolute_import 3 | from __future__ import division 4 | 5 | import os 6 | 7 | import pandas as pd 8 | 9 | from ..CoreBu import ABuEnv 10 | from ..UtilBu import ABuFileUtil 11 | 12 | SIMILAR_CACHE_PATH = os.path.join(ABuEnv.g_project_cache_dir, 'similar.hdf5') 13 | 14 | 15 | def similar_key(symbol, cmp_cnt=None, n_folds=None, start=None, end=None, corr_type=None): 16 | return '{}_{}_{}_{}_{}_{}'.format(symbol, cmp_cnt, n_folds, start, end, corr_type) 17 | 18 | 19 | def dump_2_hdh5(key, obj): 20 | ABuFileUtil.dump_hdf5(SIMILAR_CACHE_PATH, obj, key) 21 | 22 | 23 | def load_2_hdh5(key): 24 | return ABuFileUtil.load_hdf5(SIMILAR_CACHE_PATH, key) 25 | 26 | 27 | def show_keys(): 28 | with pd.HDFStore(SIMILAR_CACHE_PATH) as h5s: 29 | return h5s.keys() 30 | 31 | 32 | def clear_cache(key=None): 33 | if key is not None: 34 | ABuFileUtil.del_hdf5(SIMILAR_CACHE_PATH, key) 35 | else: 36 | ABuFileUtil.del_file(SIMILAR_CACHE_PATH) 37 | -------------------------------------------------------------------------------- /abupy/SimilarBu/ABuSimilarDrawing.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | """ 3 | 相关系数,相似度可视化模块 4 | """ 5 | from __future__ import print_function 6 | from __future__ import absolute_import 7 | from __future__ import division 8 | 9 | import itertools 10 | import math 11 | 12 | import matplotlib.pyplot as plt 13 | import numpy as np 14 | 15 | from ..MarketBu import ABuSymbolPd 16 | from ..UtilBu import ABuScalerUtil 17 | 18 | # noinspection PyUnresolvedReferences 19 | from ..CoreBu.ABuFixes import xrange 20 | from ..CoreBu import ABuEnv 21 | from ..UtilBu.ABuDTUtil import plt_show 22 | 23 | """预备颜色序列集,超出序列数量应使用itertools.cycle循环绘制""" 24 | K_PLT_MAP_STYLE = [ 25 | 'b', 'c', 'g', 'k', 'm', 'r', 'y', 'b--', 'c--', 'g--', 'k--'] 26 | 27 | 28 | def draw_show_close(sorted_ret, target_count, show_cnt): 29 | """ 30 | 通过多少个交易日参数target_count,计算出make_kl_df的参数n_folds, 31 | 使用ABuScalerUtil.scaler_std将show_cnt个最相似的股票价格序列进行 32 | 标准化在一个数量值范围内可视化 33 | :param sorted_ret: 可迭代序列,元素形如('usTSLA', 1.0), ('usSINA', 0.45565379371028253)..... 34 | :param target_count: 需要请求多少个交易日数据,int 35 | :param show_cnt: 可视化top show_cnt相关个价格走势 36 | """ 37 | if show_cnt is None and not isinstance(show_cnt, int): 38 | return 39 | # 规避sorted_ret长度不够的问题 40 | show_cnt = min(show_cnt, len(sorted_ret)) 41 | if show_cnt <= 0: 42 | return 43 | 44 | with plt_show(): 45 | # 循环K_PLT_MAP_STYLE颜色集的颜色,绘制各个金融时间序列 46 | for x, cs_color in zip(xrange(0, show_cnt), itertools.cycle(K_PLT_MAP_STYLE)): 47 | # 通过多少个交易日参数target_count,计算出要请求几年的数据n_folds 48 | n_folds = int(math.ceil(target_count / ABuEnv.g_market_trade_year)) 49 | # sorted_ret[x] : ('usTSLA', 1.0) -> sorted_ret[x][0]: usTSLA 50 | # FIXME 暂时忽略一个bug如果请求可视化时使用的是start,end,方式那么这里可视化的时间段就不符合了,需要传递完整的信息 51 | df = ABuSymbolPd.make_kl_df(sorted_ret[x][0], n_folds=n_folds) 52 | # 支可视化close_array 53 | close_array = df['close'] 54 | if target_count < len(close_array): 55 | # 再次确认时间范围 56 | close_array = close_array[:int(target_count)] 57 | 58 | cs_np = np.array(close_array, dtype=np.float) 59 | # 使用ABuScalerUtil.scaler_std将序列进行标准化在一个数量值范围内可视化 60 | plt.plot(ABuScalerUtil.scaler_std(cs_np), cs_color, label=sorted_ret[x][0]) 61 | plt.legend(loc='best', bbox_to_anchor=(1.05, 1), borderaxespad=0.) 62 | 63 | 64 | def draw_show_close_array(sorted_ret, cs_array): 65 | """ 66 | 绘制参数中cs_array序列个金融时间序列 67 | :param sorted_ret: 可迭代序列,元素形如('usTSLA', 1.0), ('usSINA', 0.45565379371028253)..... 68 | :param cs_array: 可迭代的价格序列 69 | """ 70 | # 循环K_PLT_MAP_STYLE颜色集的颜色,绘制各个金融时间序列 71 | for x, (cs_np, cs_color) in enumerate(zip(cs_array, itertools.cycle(K_PLT_MAP_STYLE))): 72 | # sorted_ret[x] : ('usTSLA', 1.0) -> sorted_ret[x][0]: usTSLA 73 | plt.plot(cs_np, cs_color, label=sorted_ret[x][0], bbox_to_anchor=(1.05, 1), loc=3, borderaxespad=0.) 74 | 75 | plt.legend(loc='best') 76 | plt.show() 77 | -------------------------------------------------------------------------------- /abupy/SimilarBu/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from . import ABuCorrcoef 4 | from . import ABuSimilar 5 | from .ABuCorrcoef import ECoreCorrType 6 | from .ABuSimilar import find_similar_with_se, find_similar_with_folds, find_similar_with_cnt 7 | 8 | __all__ = [ 9 | 'ABuSimilar', 10 | 'ABuSimilarDrawing', 11 | 'ABuCorrcoef', 12 | 'ECoreCorrType', 13 | 'find_similar_with_se', 14 | 'find_similar_with_folds', 15 | 'find_similar_with_cnt' 16 | ] 17 | -------------------------------------------------------------------------------- /abupy/SlippageBu/ABuSlippage.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | from __future__ import absolute_import 3 | 4 | # noinspection all 5 | from . import ABuSlippageBuyBase as sbb 6 | # noinspection all 7 | from . import ABuSlippageSellBase as ssb 8 | # noinspection all 9 | from . import ABuSlippageBuyMean as sbm 10 | -------------------------------------------------------------------------------- /abupy/SlippageBu/ABuSlippageBuyBase.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | """ 3 | 日内滑点买入价格决策基础模块:暂时迁移简单实现方式,符合回测需求,如迁移实盘模块 4 | 需添加日内择时策略,通过日内分钟k线,实现日内分钟k线择时,更微观的 5 | 实现日内择时滑点功能,不考虑大资金的冲击成本及系统外的大幅滑点 6 | """ 7 | 8 | from __future__ import division 9 | from __future__ import print_function 10 | from __future__ import absolute_import 11 | 12 | from abc import ABCMeta, abstractmethod 13 | import functools 14 | 15 | import numpy as np 16 | 17 | from ..CoreBu.ABuFixes import six 18 | 19 | __author__ = '阿布' 20 | __weixin__ = 'abu_quant' 21 | 22 | 23 | class AbuSlippageBuyBase(six.with_metaclass(ABCMeta, object)): 24 | """非高频日内滑点买入决策抽象基类""" 25 | 26 | def __init__(self, kl_pd_buy, factor_name): 27 | """ 28 | :param kl_pd_buy: 交易当日的交易数据 29 | :param factor_name: ABuFactorBuyBases子类实例对象的factor_name 30 | """ 31 | self.buy_price = np.inf 32 | self.kl_pd_buy = kl_pd_buy 33 | self.factor_name = factor_name 34 | 35 | def fit(self): 36 | """做基础验证比如今天是否停盘后调用fit_price""" 37 | if self.kl_pd_buy.empty or self.kl_pd_buy.volume == 0: 38 | # 买入时正无穷为放弃单子 39 | return np.inf 40 | 41 | return self.fit_price() 42 | 43 | @abstractmethod 44 | def fit_price(self): 45 | """ 46 | 子类主要需要实现的函数,决策交易当日的最终买入价格 47 | :return: 最终决策的当前交易买入价格 48 | """ 49 | pass 50 | 51 | """是否开启涨停板滑点买入价格特殊处理, 默认关闭,外部修改如:abupy.slippage.sbb.g_enable_limit_up = True""" 52 | g_enable_limit_up = False 53 | """ 54 | 初始设定涨停板买入成交概率100%,这里也可以在计算完一次概率后,再使用成交量做二次概率计算, 55 | 外部修改如:abupy.slippage.sbb.g_limit_up_deal_chance = 0.5,即修改为买入概率50% 56 | """ 57 | g_limit_up_deal_chance = 1 58 | """在集合竞价阶段价格已经达成涨停的情况下买入成功的概率,默认0.2, 即20%成功概率""" 59 | g_pre_limit_up_rate = 0.2 60 | 61 | 62 | def slippage_limit_up(func): 63 | """ 64 | 针对a股涨停板买入价格决策的装饰器,子类可选择装饰与不装饰在fit_price上 65 | 如果是实盘策略中,使用分钟k线,及日内择时策略,即不需特别处理。 66 | 回测中需要特别处理,处理买入成功概率,根据概率决定是否能买入, 67 | 及涨停下的买入价格决策,涨停下买入价格模型为,越靠近涨停价格 68 | 买入成交概率越大,即在涨停下预期以靠近涨停价格买入,缺点是使用了随机数, 69 | 导致回测结果将出现不一致的情况 70 | """ 71 | @functools.wraps(func) 72 | def wrapper(self, *args, **kwargs): 73 | if g_enable_limit_up and self.kl_pd_buy.p_change >= 10 and self.kl_pd_buy.high == self.kl_pd_buy.close: 74 | """ 75 | 涨停板命中后需要根据涨停板买入成交概率(g_limit_up_deal_chance)来作为 76 | 二项式分布的概率值计算买入成功概率 77 | """ 78 | if self.kl_pd_buy.high == self.kl_pd_buy.low: 79 | # 10个点,且最高=最低,即a股在集合竞价阶段达成涨停,买入成功概率降低到g_limit_up_deal_chance * 0.2 80 | # TODO 这个概率最好使用成交量当日来计算出来 81 | limit_up_deal_chance = g_limit_up_deal_chance * g_pre_limit_up_rate 82 | else: 83 | limit_up_deal_chance = g_limit_up_deal_chance 84 | 85 | deal = np.random.binomial(1, limit_up_deal_chance) 86 | if deal: 87 | if self.kl_pd_buy.high == self.kl_pd_buy.low: 88 | return self.kl_pd_buy.high 89 | 90 | # 买入成功后需要进一步决策价位,首选arange出一个从低到涨停价格的序列,间隔0.01 91 | price_lh = np.arange(self.kl_pd_buy.low, self.kl_pd_buy.high, 0.01) 92 | # 构造概率序列,可以使用其它比如指数分布等,提高以涨停价格买入的概率,这里只使用最简单方式 93 | lh_chance = np.linspace(0, 1, len(price_lh)) 94 | """ 95 | 计算出对应的概率, 这里的概率分布并不陡峭,即涨停价格附近权重并不是很高, 96 | 可以使用如:np.power(price_hl, len(price_hl) / 2) / np.power(price_hl, len(price_hl) / 2).sum() 97 | 来进一步提升涨跌板附近价格的买入权重 98 | """ 99 | # noinspection PyUnresolvedReferences 100 | p = lh_chance / lh_chance.sum() 101 | # 最后使用随机加权概率抽取,选中一个买入涨停价格 102 | return np.random.choice(price_lh, 1, p=p)[0] 103 | # 没能成交返回正无穷 104 | return np.inf 105 | else: 106 | return func(self, *args, **kwargs) 107 | return wrapper 108 | -------------------------------------------------------------------------------- /abupy/SlippageBu/ABuSlippageBuyMean.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | """ 3 | 日内滑点买入示例实现:均价买入 4 | 最简单的回测买入方式,优点简单,且回测高效,在回测交易 5 | 数量足够多的前提下也能接近实盘 6 | """ 7 | 8 | from __future__ import division 9 | from __future__ import print_function 10 | from __future__ import absolute_import 11 | 12 | import numpy as np 13 | 14 | from .ABuSlippageBuyBase import AbuSlippageBuyBase, slippage_limit_up 15 | 16 | __author__ = '阿布' 17 | __weixin__ = 'abu_quant' 18 | 19 | """外部修改默认下跌阀值使用如:abupy.slippage.sbm.g_open_down_rate = 0.02""" 20 | g_open_down_rate = 0.07 21 | 22 | 23 | class AbuSlippageBuyMean(AbuSlippageBuyBase): 24 | """示例日内滑点均价买入类""" 25 | 26 | @slippage_limit_up 27 | def fit_price(self): 28 | """ 29 | 取当天交易日的最高最低均价做为决策价格 30 | :return: 最终决策的当前交易买入价格 31 | """ 32 | 33 | # TODO 基类提取作为装饰器函数,子类根据需要选择是否装饰,并且添加上根据order的call,put明确细节逻辑 34 | if self.kl_pd_buy.pre_close == 0 or (self.kl_pd_buy.open / self.kl_pd_buy.pre_close) < (1 - g_open_down_rate): 35 | # 开盘就下跌一定比例阀值,放弃单子 36 | return np.inf 37 | # 买入价格为当天均价,即最高,最低的平均,也可使用高开低收平均等方式计算 38 | self.buy_price = np.mean([self.kl_pd_buy['high'], self.kl_pd_buy['low']]) 39 | # 返回最终的决策价格 40 | return self.buy_price 41 | -------------------------------------------------------------------------------- /abupy/SlippageBu/ABuSlippageSellBase.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | """ 3 | 日内滑点卖出价格决策基础模块:暂时迁移简单实现方式,符合回测需求,如迁移实盘模块 4 | 需添加日内择时策略,通过日内分钟k线,实现日内分钟k线择时,更微观的 5 | 实现日内择时滑点功能,不考虑大资金的冲击成本及系统外的大幅滑点 6 | """ 7 | 8 | from __future__ import division 9 | from __future__ import print_function 10 | from __future__ import absolute_import 11 | 12 | from abc import ABCMeta, abstractmethod 13 | import functools 14 | 15 | import numpy as np 16 | 17 | from ..CoreBu.ABuFixes import six 18 | 19 | __author__ = '阿布' 20 | __weixin__ = 'abu_quant' 21 | 22 | 23 | class AbuSlippageSellBase(six.with_metaclass(ABCMeta, object)): 24 | """非高频日内滑点卖出决策抽象基类""" 25 | 26 | def __init__(self, kl_pd_sell, factor_name): 27 | """ 28 | :param kl_pd_sell: 交易当日的交易数据 29 | :param factor_name: ABuFactorSellBase实例对象的factor_name 30 | """ 31 | self.sell_price = np.inf 32 | self.kl_pd_sell = kl_pd_sell 33 | self.factor_name = factor_name 34 | 35 | def fit(self): 36 | """做基础验证比如今天是否停盘后调用fit_price""" 37 | if self.kl_pd_sell.empty or self.kl_pd_sell.volume == 0: 38 | # 卖出时负无穷为放弃单子 39 | return -np.inf 40 | 41 | return self.fit_price() 42 | 43 | @abstractmethod 44 | def fit_price(self): 45 | """ 46 | 子类主要需要实现的函数,决策交易当日的最终卖出价格 47 | :return: 最终决策的当前交易卖出价格 48 | """ 49 | pass 50 | 51 | """是否开启跌停板滑点卖出价格特殊处理,默认关闭,外部修改如:abupy.slippage.ssb.g_enable_limit_down = True""" 52 | g_enable_limit_down = False 53 | """ 54 | 初始设定跌停板卖出成交概率100%,这里也可以在计算完一次概率后,再使用成交量做二次概率计算, 55 | 外部修改如:abupy.slippage.ssb.g_limit_down_deal_chance = 0.5,即修改为50%成功卖出概率 56 | """ 57 | g_limit_down_deal_chance = 1 58 | """在集合竞价阶段价格已达成跌停的情况下卖出成功的概率,默认0.2, 即20%成功概率""" 59 | g_pre_limit_down_rate = 0.2 60 | 61 | 62 | def slippage_limit_down(func): 63 | """ 64 | 针对a股跌停板卖出价格决策的装饰器,子类可选择装饰与不装饰在fit_price上 65 | 如果是实盘策略中,使用分钟k线,及日内择时策略子策略,即不需特别处理。 66 | 回测中需要特别处理,处理卖出成功概率,根据概率决定是否能卖出, 67 | 及跌停下的卖出价格决策,跌停下卖出价格模型为,越靠近跌停板价格 68 | 卖出成交概率越大, 即在跌停下预期以靠近跌停价格卖出,缺点是使用了随机数, 69 | 导致回测结果将出现不一致的情况 70 | """ 71 | @functools.wraps(func) 72 | def wrapper(self, *args, **kwargs): 73 | if g_enable_limit_down and self.kl_pd_sell.p_change <= -10 and self.kl_pd_sell.low == self.kl_pd_sell.close: 74 | """ 75 | 跌停板命中后需要根据跌停板买入成交概率(g_limit_down_deal_chance)来作为 76 | 二项式分布的概率值计算卖出成功概率 77 | """ 78 | 79 | if self.kl_pd_sell.high == self.kl_pd_sell.low: 80 | # 10个点,且最高=最低,即a股在集合竞价阶段达成跌停,卖出成功概率降低到g_limit_down_deal_chance * 0.2 81 | # TODO 这个概率最好使用成交量当日来计算出来 82 | limit_down_deal_chance = g_limit_down_deal_chance * g_pre_limit_down_rate 83 | else: 84 | limit_down_deal_chance = g_limit_down_deal_chance 85 | 86 | deal = np.random.binomial(1, limit_down_deal_chance) 87 | if deal: 88 | # 卖出成功后需要进一步决策价位,首选arange出一个从高到跌停价格的序列,间隔-0.01 89 | if self.kl_pd_sell.high == self.kl_pd_sell.low: 90 | return self.kl_pd_sell.low 91 | 92 | price_hl = np.arange(self.kl_pd_sell.high, self.kl_pd_sell.low, -0.01) 93 | hl_chance = np.linspace(0, 1, len(price_hl)) 94 | # noinspection PyUnresolvedReferences 95 | p = hl_chance / hl_chance.sum() 96 | # 最后使用随机加权概率抽取,选中一个卖出价格 97 | return np.random.choice(price_hl, 1, p=p)[0] 98 | # 没能成交返回负无穷 99 | return -np.inf 100 | else: 101 | return func(self, *args, **kwargs) 102 | return wrapper 103 | -------------------------------------------------------------------------------- /abupy/SlippageBu/ABuSlippageSellMean.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | """ 3 | 日内滑点卖出示例实现:均价卖出 4 | 最简单的回测卖出方式,优点简单,且回测高效,在回测交易 5 | 数量足够多的前提下也能接近实盘 6 | """ 7 | 8 | from __future__ import division 9 | from __future__ import print_function 10 | from __future__ import absolute_import 11 | 12 | import numpy as np 13 | 14 | from .ABuSlippageSellBase import AbuSlippageSellBase, slippage_limit_down 15 | 16 | __author__ = '阿布' 17 | __weixin__ = 'abu_quant' 18 | 19 | 20 | class AbuSlippageSellMean(AbuSlippageSellBase): 21 | """示例日内滑点均价卖出类""" 22 | 23 | @slippage_limit_down 24 | def fit_price(self): 25 | """ 26 | 取当天交易日的最高最低均价做为决策价格 27 | :return: 最终决策的当前交易卖出价格 28 | """ 29 | 30 | self.sell_price = np.mean([self.kl_pd_sell['high'], self.kl_pd_sell['low']]) 31 | return self.sell_price 32 | -------------------------------------------------------------------------------- /abupy/SlippageBu/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from .ABuSlippageBuyBase import AbuSlippageBuyBase 4 | from .ABuSlippageBuyMean import AbuSlippageBuyMean 5 | from .ABuSlippageSellBase import AbuSlippageSellBase 6 | from .ABuSlippageSellMean import AbuSlippageSellMean 7 | 8 | from . import ABuSlippage as slippage 9 | 10 | __all__ = [ 11 | 'AbuSlippageBuyBase', 12 | 'AbuSlippageBuyMean', 13 | 'AbuSlippageSellBase', 14 | 'AbuSlippageSellMean', 15 | 16 | 'slippage'] 17 | -------------------------------------------------------------------------------- /abupy/TLineBu/ABuTL.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from . import ABuTLine as line 4 | from . import ABuTLExecute as execute 5 | from . import ABuTLAtr as atr 6 | from . import ABuTLGolden as golden 7 | from . import ABuTLJump as jump 8 | from . import ABuTLSimilar as similar 9 | from . import ABuTLVwap as vwap 10 | from . import ABuTLWave as wave 11 | from .ABuTLine import ESkeletonHow, EShiftDistanceHow, AbuTLine 12 | 13 | __all__ = [ 14 | 'line', 15 | 'execute', 16 | 'atr', 17 | 'golden', 18 | 'jump', 19 | 'similar', 20 | 'vwap', 21 | 'wave', 22 | 23 | 'ESkeletonHow', 24 | 'EShiftDistanceHow', 25 | 'AbuTLine'] 26 | -------------------------------------------------------------------------------- /abupy/TLineBu/ABuTLAtr.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | """ 3 | 计算线atr模块 4 | """ 5 | 6 | from __future__ import division 7 | from __future__ import print_function 8 | from __future__ import absolute_import 9 | 10 | import matplotlib.pyplot as plt 11 | import numpy as np 12 | import pandas as pd 13 | 14 | from ..TLineBu.ABuTLine import AbuTLine 15 | from ..CoreBu.ABuPdHelper import pd_rolling_std, pd_ewm_std 16 | 17 | __author__ = '阿布' 18 | __weixin__ = 'abu_quant' 19 | 20 | 21 | def show_atr_std(kl_pd): 22 | """ 23 | 可视化atr移动平均std和加权移动平均std, 24 | 注意会修改kl_pd,只做测试使用,内部未做copy处理, 25 | 如不能改动,外部自copy操作,再传递进来 26 | :param kl_pd: 金融时间序列,pd.DataFrame对象 27 | """ 28 | 29 | pre_atr21 = kl_pd['atr21'].shift(1) 30 | # noinspection PyTypeChecker 31 | kl_pd['atr_change'] = np.where(pre_atr21 == 0, 0, np.log(kl_pd['atr21'] / pre_atr21)) 32 | kl_pd['mov_std'] = pd_rolling_std(kl_pd['atr_change'], window=20, center=False) * np.sqrt(20) 33 | kl_pd['std_ewm'] = pd_ewm_std(kl_pd['atr_change'], span=20, min_periods=20, adjust=True) * np.sqrt(20) 34 | kl_pd[['close', 'atr21', 'mov_std', 'std_ewm', 'atr_change']].plot(subplots=True, figsize=(16, 12), grid=True) 35 | plt.show() 36 | 37 | 38 | def calc_atr_std(kl_pd, xd=21, ewm=True, show=True): 39 | """ 40 | 计算atr移动平均std或者加权移动平均std技术线,使用 41 | AbuTLine封装技术线实体,不会修改kl_pd,返回AbuTLine对象 42 | :param kl_pd: 金融时间序列,pd.DataFrame对象 43 | :param xd: 计算移动平均std或加权移动平均std使用的窗口参数,默认21 44 | :param ewm: 是否使用加权移动平均std计算 45 | :param show: 是否可视化,可视化使用AbuTLine.show接口 46 | :return: 返回AbuTLine对象 47 | """ 48 | pre_atr21 = kl_pd['atr21'].shift(1) 49 | # noinspection PyTypeChecker 50 | atr_change = np.where(pre_atr21 == 0, 0, np.log(kl_pd['atr21'] / pre_atr21)) 51 | 52 | if ewm: 53 | atr_roll_std = pd_ewm_std(atr_change, span=xd, min_periods=1, adjust=True) * np.sqrt(xd) 54 | else: 55 | atr_roll_std = pd_rolling_std(atr_change, window=xd, min_periods=1, center=False) * np.sqrt(xd) 56 | 57 | # min_periods=1还是会有两个nan,填了 58 | atr_roll_std = pd.Series(atr_roll_std).fillna(method='bfill') 59 | # 主要目的就是通过atr_roll_std构造line 60 | line = AbuTLine(atr_roll_std, 'atr std') 61 | if show: 62 | line.show() 63 | 64 | return line 65 | -------------------------------------------------------------------------------- /abupy/TLineBu/ABuTLGolden.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | """ 3 | 黄金分割及比例分割示例模块 4 | """ 5 | 6 | from __future__ import print_function 7 | from __future__ import absolute_import 8 | from __future__ import division 9 | 10 | from collections import namedtuple 11 | 12 | import matplotlib.pyplot as plt 13 | 14 | from ..TLineBu import ABuTLExecute 15 | from ..UtilBu.ABuDTUtil import plt_show 16 | 17 | __author__ = '阿布' 18 | __weixin__ = 'abu_quant' 19 | 20 | 21 | def calc_golden(kl_pd, show=True): 22 | """ 23 | 只针对金融时间序列的收盘价格close序列,进行黄金分割及比例分割 24 | 数值结果分析以及可视化 25 | :param kl_pd: 金融时间序列,pd.DataFrame对象 26 | :param show: 是否可视化黄金分割及比例分割结果 27 | :return: 黄金分割及比例分割结果组成的namedtuple数值对象 28 | """ 29 | kl_close = kl_pd.close 30 | 31 | if not hasattr(kl_pd, 'name'): 32 | # 金融时间序列中如果有异常的没有name信息的补上一个unknown 33 | kl_pd.name = 'unknown' 34 | 35 | # 计算视觉黄金分割 36 | gd_382, gd_500, gd_618 = ABuTLExecute.find_golden_point(kl_pd.index, kl_close) 37 | # 计算统计黄金分割 38 | gex_382, gex_500, gex_618 = ABuTLExecute.find_golden_point_ex(kl_pd.index, kl_close) 39 | 40 | # below above 382, 618确定,即382,618上下底 41 | below618, above618 = ABuTLExecute.below_above_gen(gd_618, gex_618) 42 | below382, above382 = ABuTLExecute.below_above_gen(gd_382, gex_382) 43 | 44 | # 再次通过比例序列percents和find_percent_point寻找对应比例的位置字典pts_dict 45 | percents = [0.20, 0.25, 0.30, 0.70, 0.80, 0.90, 0.95] 46 | pts_dict = ABuTLExecute.find_percent_point(percents, kl_close) 47 | 48 | # 0.20, 0.25, 0.30只找最低的,即底部只要最低的 49 | below200, _ = ABuTLExecute.below_above_gen(*pts_dict[0.20]) 50 | below250, _ = ABuTLExecute.below_above_gen(*pts_dict[0.25]) 51 | below300, _ = ABuTLExecute.below_above_gen(*pts_dict[0.30]) 52 | 53 | # 0.70, 0.80, 0.90, 0.95只找最高的,即顶部只要最高的 54 | _, above700 = ABuTLExecute.below_above_gen(*pts_dict[0.70]) 55 | _, above800 = ABuTLExecute.below_above_gen(*pts_dict[0.80]) 56 | _, above900 = ABuTLExecute.below_above_gen(*pts_dict[0.90]) 57 | _, above950 = ABuTLExecute.below_above_gen(*pts_dict[0.95]) 58 | 59 | if show: 60 | with plt_show(): 61 | # 开始可视化黄金分割及比例分割结果 62 | plt.axes([0.025, 0.025, 0.95, 0.95]) 63 | plt.plot(kl_close) 64 | 65 | # 0.70, 0.80, 0.90, 0.95,lw线条粗度递减 66 | plt.axhline(above950, lw=3.5, color='c') 67 | plt.axhline(above900, lw=3.0, color='y') 68 | plt.axhline(above800, lw=2.5, color='k') 69 | plt.axhline(above700, lw=2.5, color='m') 70 | 71 | # 中间层的618是带,有上下底 72 | plt.axhline(above618, lw=2, color='r') 73 | plt.axhline(below618, lw=1.5, color='r') 74 | plt.fill_between(kl_pd.index, above618, below618, 75 | alpha=0.1, color="r") 76 | # 中间层的382是带,有上下底 77 | plt.axhline(above382, lw=1.5, color='g') 78 | plt.axhline(below382, lw=2, color='g') 79 | plt.fill_between(kl_pd.index, above382, below382, 80 | alpha=0.1, color="g") 81 | 82 | # 0.20, 0.25, 0.30 lw线条粗度递曾 83 | plt.axhline(below300, lw=2.5, color='k') 84 | plt.axhline(below250, lw=3.0, color='y') 85 | plt.axhline(below200, lw=3.5, color='c') 86 | 87 | _ = plt.setp(plt.gca().get_xticklabels(), rotation=30) 88 | plt.legend([kl_pd.name, 'above950', 'above900', 'above800', 'above700', 'above618', 'below618', 89 | 'above382', 'below382', 'below300', 'below250', 'below200'], bbox_to_anchor=(1.05, 1), loc=2, 90 | borderaxespad=0.) 91 | plt.title('between golden') 92 | 93 | return namedtuple('golden', ['g382', 'gex382', 'g500', 'gex500', 'g618', 94 | 'gex618', 'above618', 'below618', 'above382', 'below382', 95 | 'above950', 'above900', 'above800', 'above700', 'below300', 'below250', 'below200'])( 96 | gd_382, gex_382, 97 | gd_500, gex_500, gd_618, gex_618, above618, below618, above382, below382, 98 | above950, above900, above800, above700, below300, below250, below200) 99 | -------------------------------------------------------------------------------- /abupy/TLineBu/ABuTLVwap.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | """ 3 | VWAP: Volume Weighted Average Price 成交量加权平均价 4 | 5 | 非标准传统意义vwap计算,即非使用高频的分钟k线和量进行计算,只是套用概念计算 6 | 日线级别的vwap 7 | """ 8 | from __future__ import division 9 | from __future__ import print_function 10 | from __future__ import absolute_import 11 | 12 | from enum import Enum 13 | 14 | import numpy as np 15 | 16 | from ..TLineBu.ABuTLine import AbuTLine 17 | 18 | 19 | # TODO 重构时提到上级模块中 20 | class EDayBarCalcType(Enum): 21 | """计算金融序列最终price使用的方法""" 22 | 23 | """高开低收的平均值""" 24 | OHLC_MEAN = 0 25 | """高开低收的中位数""" 26 | OHLC_MEDIAN = 1 27 | """高低的平均值""" 28 | HL_MEAN = 2 29 | """使用close价格""" 30 | CLOSE = 3 31 | 32 | 33 | def calc_vwap(kl_pd, how=EDayBarCalcType.OHLC_MEAN, show=True): 34 | """ 35 | 非标准传统意义vwap计算,即非使用高频的分钟k线和量进行计算,只是套用概念计算 36 | 日线级别的vwap,使用EDayBarCalcType确定日线级别上的最终点位vwap序列,即确定 37 | 计算vwap使用的价格序列,需要注意成交量的数据准确度问题,且对异常成交量需要进行 38 | 控制筛选 39 | :param kl_pd: 金融时间序列,pd.DataFrame对象 40 | :param how: EDayBarCalcType,计算确定日线级别上的最终点位价格序列使用的方法 41 | :param show: 是否可视化,可视化使用AbuTLine.show接口 42 | :return: 返回AbuTLine对象 43 | """ 44 | if how == EDayBarCalcType.OHLC_MEAN: 45 | # 日k级别上高开低收的平均 46 | price = np.mean([kl_pd.high, kl_pd.open, kl_pd.close, kl_pd.low], axis=0) 47 | elif how == EDayBarCalcType.OHLC_MEDIAN: 48 | # 日k级别上高开低收的中位数 49 | price = np.median([kl_pd.high, kl_pd.open, kl_pd.close, kl_pd.low], axis=0) 50 | elif how == EDayBarCalcType.HL_MEAN: 51 | # 日k级别上高低的平均价格 52 | price = np.mean([kl_pd.high, kl_pd.low], axis=0) 53 | elif how == EDayBarCalcType.CLOSE: 54 | # 日k级别上直接使用收close 55 | price = kl_pd.close 56 | else: 57 | raise TypeError('calc_vwap_std how is error! how= {}'.format(how)) 58 | 59 | # 使用得到价格序列做基础计算vwap 60 | vwap = (kl_pd.volume * price).sum() / kl_pd.volume.sum() 61 | # 主要目的就是通过vwap构造line, 这里设置了price为line,使用mean=vwap,详阅AbuTLine 62 | line = AbuTLine(price, 'vwap std', mean=vwap) 63 | if show: 64 | line.show() 65 | 66 | return line 67 | -------------------------------------------------------------------------------- /abupy/TLineBu/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from . import ABuTL as tl 4 | 5 | __all__ = ['tl'] 6 | -------------------------------------------------------------------------------- /abupy/TradeBu/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from .ABuBenchmark import AbuBenchmark 4 | from .ABuCapital import AbuCapital 5 | from .ABuKLManager import AbuKLManager 6 | from .ABuOrder import AbuOrder 7 | 8 | from . import ABuMLFeature as feature 9 | from .ABuMLFeature import AbuFeatureDegExtend 10 | 11 | from .ABuMLFeature import AbuFeatureBase, BuyFeatureMixin, SellFeatureMixin 12 | from .ABuTradeProxy import AbuOrderPdProxy, EOrderSameRule 13 | 14 | 15 | from . import ABuTradeDrawer 16 | from . import ABuTradeExecute 17 | from . import ABuTradeProxy 18 | 19 | __all__ = [ 20 | 'AbuBenchmark', 21 | 'AbuCapital', 22 | 'AbuKLManager', 23 | 'AbuOrder', 24 | 'AbuOrderPdProxy', 25 | 'EOrderSameRule', 26 | 27 | 'feature', 28 | 'AbuFeatureDegExtend', 29 | 'AbuFeatureBase', 30 | 'BuyFeatureMixin', 31 | 'SellFeatureMixin', 32 | 'ABuTradeDrawer', 33 | 'ABuTradeExecute', 34 | 'ABuTradeProxy'] 35 | -------------------------------------------------------------------------------- /abupy/UmpBu/ABuUmp.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | # noinspection all 4 | from . import ABuUmpEdgeBase as edge 5 | # noinspection all 6 | from . import ABuUmpMainBase as main 7 | # noinspection all 8 | from . import ABuUmpManager as manager 9 | # noinspection PyUnresolvedReferences 10 | from .ABuUmpBase import ump_main_make_xy, ump_edge_make_xy 11 | # noinspection PyUnresolvedReferences 12 | from .ABuUmpEdgeBase import EEdgeType 13 | -------------------------------------------------------------------------------- /abupy/UmpBu/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from .ABuUmpBase import CachedUmpManager, AbuUmpBase, BuyUmpMixin, SellUmpMixin 4 | 5 | from .ABuUmpEdgeBase import AbuUmpEdgeBase 6 | from .ABuUmpEdgeDeg import AbuUmpEdgeDeg, AbuUmpEegeDegExtend 7 | from .ABuUmpEdgeFull import AbuUmpEdgeFull 8 | from .ABuUmpEdgeMul import AbuUmpEdgeMul 9 | from .ABuUmpEdgePrice import AbuUmpEdgePrice 10 | from .ABuUmpEdgeWave import AbuUmpEdgeWave 11 | 12 | from .ABuUmpMainBase import AbuUmpMainBase 13 | from .ABuUmpMainDeg import AbuUmpMainDeg, AbuUmpMainDegExtend 14 | from .ABuUmpMainFull import AbuUmpMainFull 15 | from .ABuUmpMainJump import AbuUmpMainJump 16 | from .ABuUmpMainMul import AbuUmpMainMul 17 | from .ABuUmpMainPrice import AbuUmpMainPrice 18 | from .ABuUmpMainWave import AbuUmpMainWave 19 | 20 | from . import ABuUmp as ump 21 | 22 | __all__ = [ 23 | 'CachedUmpManager', 24 | 'AbuUmpBase', 25 | 'BuyUmpMixin', 26 | 'SellUmpMixin', 27 | 28 | 'AbuUmpEdgeBase', 29 | 'AbuUmpEdgeDeg', 30 | 'AbuUmpEegeDegExtend', 31 | 'AbuUmpEdgeFull', 32 | 'AbuUmpEdgeMul', 33 | 'AbuUmpEdgePrice', 34 | 'AbuUmpEdgeWave', 35 | 36 | 'AbuUmpMainBase', 37 | 'AbuUmpMainDeg', 38 | 'AbuUmpMainDegExtend', 39 | 'AbuUmpMainFull', 40 | 'AbuUmpMainJump', 41 | 'AbuUmpMainMul', 42 | 'AbuUmpMainPrice', 43 | 'AbuUmpMainWave', 44 | 45 | 'ump'] 46 | -------------------------------------------------------------------------------- /abupy/UtilBu/ABuLazyUtil.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | """ 3 | lazy工具模块 4 | """ 5 | 6 | from __future__ import print_function 7 | from __future__ import absolute_import 8 | from __future__ import division 9 | 10 | import sys 11 | import weakref 12 | 13 | 14 | class LazyFunc(object): 15 | """描述器类:作用在类中需要lazy的对象方法上""" 16 | 17 | def __init__(self, func): 18 | """ 19 | 外部使用eg: 20 | class BuyCallMixin(object): 21 | @LazyFunc 22 | def buy_type_str(self): 23 | return "call" 24 | 25 | @LazyFunc 26 | def expect_direction(self): 27 | return 1.0 28 | """ 29 | self.func = func 30 | self.cache = weakref.WeakKeyDictionary() 31 | 32 | def __get__(self, instance, owner): 33 | """描述器__get__,使用weakref.WeakKeyDictionary将以实例化的instance加入缓存""" 34 | if instance is None: 35 | return self 36 | try: 37 | return self.cache[instance] 38 | except KeyError: 39 | ret = self.func(instance) 40 | self.cache[instance] = ret 41 | return ret 42 | 43 | def __set__(self, instance, value): 44 | """描述器__set__,raise AttributeError,即禁止外部set值""" 45 | raise AttributeError("LazyFunc set value!!!") 46 | 47 | def __delete__(self, instance): 48 | """描述器___delete__从weakref.WeakKeyDictionary cache中删除instance""" 49 | del self.cache[instance] 50 | 51 | 52 | class LazyClsFunc(LazyFunc): 53 | """ 54 | 描述器类: 55 | 作用在类中需要lazy的类方法上,实际上只是使用__get__(owner, owner) 56 | 替换原始__get__(self, instance, owner) 57 | """ 58 | 59 | def __get__(self, instance, owner): 60 | """描述器__get__,使用__get__(owner, owner)替换原始__get__(self, instance, owner)""" 61 | return super(LazyClsFunc, self).__get__(owner, owner) 62 | 63 | 64 | def add_doc(func, doc): 65 | """Lazy add doc""" 66 | func.__doc__ = doc 67 | 68 | 69 | def import_module(name): 70 | """Lazy impor _module""" 71 | __import__(name) 72 | return sys.modules[name] 73 | -------------------------------------------------------------------------------- /abupy/UtilBu/ABuMacUtil.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | """mac os 平台工具模块""" 3 | 4 | from __future__ import print_function 5 | from __future__ import absolute_import 6 | from __future__ import division 7 | 8 | import os 9 | import socket 10 | 11 | from ..UtilBu.ABuStrUtil import to_native_str 12 | 13 | 14 | def socket_bind_recv(socket_fn, cmd_handler): 15 | """ 16 | 基于bsd系统的进程间socket通信,接受消息,处理消息 17 | :param socket_fn: socket文件名称 18 | :param cmd_handler: cmd处理函数,callable类型 19 | """ 20 | if not callable(cmd_handler): 21 | print('socket_bind_recv cmd_handler must callable!') 22 | 23 | server = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) 24 | server.bind(socket_fn) 25 | server.listen(0) 26 | while True: 27 | connection, _ = server.accept() 28 | socket_cmd = connection.recv(1024).decode() 29 | # 把接收到的socket传递给外部对应的处理函数 30 | cmd_handler(socket_cmd) 31 | connection.close() 32 | 33 | 34 | def socket_send_msg(socket_fn, msg): 35 | """ 36 | 基于bsd系统的进程间socket通信,发送消息 37 | :param socket_fn: : socket文件名称 38 | :param msg: 字符串类型需要传递的数据,不需要encode,内部进行encode 39 | """ 40 | client = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) 41 | client.connect(socket_fn) 42 | client.send(msg.encode()) 43 | client.close() 44 | 45 | 46 | def show_msg(title, msg): 47 | """ 48 | 使用osascript脚步提示弹窗,主要用在长时间且耗时的任务中,提示重要问题信息 49 | :param title: 弹窗标题 50 | :param msg: 弹窗信息 51 | """ 52 | # 注意这里要把msg统一转换回bytes 53 | msg_cmd = 'osascript -e \'display notification "%s" with title "%s"\'' % (to_native_str(msg), to_native_str(title)) 54 | os.system(msg_cmd) 55 | 56 | 57 | def fold_free_size_mb(folder): 58 | """ 59 | mac os下剩余磁盘空间获取 60 | :param folder: 目标目录 61 | :return: 返回float,单位mb 62 | """ 63 | st = os.statvfs(folder) 64 | return st.f_bavail * st.f_frsize / 1024 / 1024 65 | -------------------------------------------------------------------------------- /abupy/UtilBu/ABuMd5.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | """ 3 | md5, crc32等加密,变换匹配模块 4 | """ 5 | 6 | from __future__ import print_function 7 | from __future__ import absolute_import 8 | from __future__ import division 9 | 10 | import hashlib 11 | import os 12 | from binascii import crc32 13 | 14 | # noinspection PyUnresolvedReferences 15 | from ..CoreBu.ABuFixes import xrange 16 | from ..CoreBu import ABuEnv 17 | 18 | K_BYTE_SIZE = 1024 19 | 20 | 21 | def _md5_obj(): 22 | """根据python版本返回md5实例""" 23 | md5_obj = hashlib.md5() if ABuEnv.g_is_py3 else hashlib.new("md5") 24 | return md5_obj 25 | 26 | 27 | def md5_from_binary(binary): 28 | """对字符串进行md5, 返回md5后32位字符串对象""" 29 | m = _md5_obj() 30 | m.update(binary.encode('utf-8')) 31 | return m.hexdigest() 32 | 33 | 34 | def md5_from_file(fn, block_m=1): 35 | """ 36 | 对文件进行md5, 分块读取文件 37 | :param fn: 目标文件路径 38 | :param block_m: 分块读取大小,默认1mb 39 | :return: md5后32位字符串对象, md5失败等问题返回0 40 | """ 41 | opened = False 42 | f_obj = None 43 | if hasattr(fn, "read"): 44 | f_obj = fn 45 | else: 46 | if os.path.exists(fn) and os.path.isfile(fn): 47 | f_obj = open(fn, "rb") 48 | opened = True 49 | if f_obj: 50 | block_b = block_m * K_BYTE_SIZE * K_BYTE_SIZE 51 | try: 52 | m = _md5_obj() 53 | while True: 54 | fb = f_obj.read(block_b) 55 | if not fb: 56 | break 57 | m.update(fb) 58 | finally: 59 | if opened: 60 | f_obj.close() 61 | return m.hexdigest() 62 | else: 63 | return 0 64 | 65 | 66 | def crc32_from_file(fn, block_m=1): 67 | """ 68 | 对文件进行crc32, 分块读取文件 69 | :param fn: 目标文件路径 70 | :param block_m: 分块读取大小,默认1mb 71 | :return: crc32后返回的16进制字符串 eg. '0x00000000' 72 | """ 73 | if os.path.exists(fn) and os.path.isfile(fn): 74 | block_b = block_m * K_BYTE_SIZE * K_BYTE_SIZE 75 | crc = 0 76 | f = open(fn, "rb") 77 | while True: 78 | fb = f.read(block_b) 79 | if not fb: 80 | break 81 | crc = crc32(fb, crc) 82 | f.close() 83 | res = '' 84 | for _ in xrange(4): 85 | t = crc & 0xFF 86 | crc >>= 8 87 | res = '%02x%s' % (t, res) 88 | return "0x" + res 89 | else: 90 | return 0 91 | -------------------------------------------------------------------------------- /abupy/UtilBu/ABuOsUtil.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | """操作系统工具函数整合模块""" 3 | 4 | from __future__ import print_function 5 | from __future__ import absolute_import 6 | from __future__ import division 7 | 8 | import logging 9 | 10 | from ..CoreBu import ABuEnv 11 | from ..UtilBu.ABuDTUtil import catch_error 12 | 13 | log_func = logging.info if ABuEnv.g_is_ipython else print 14 | 15 | 16 | @catch_error() 17 | def show_msg(title, msg, log=False): 18 | """ 19 | 统一平台弹窗信息提示,被catch_error装饰,即不应该被提示中断程序, 20 | 特别长任务的情况下 21 | :param title: 弹窗信息标题 22 | :param msg: 弹窗信息内容 23 | :param log: 是否通过logging.info打印信息 24 | :return: 25 | """ 26 | # 由于catch_error忽略错误,所有主要信息还是先打印 27 | if log: 28 | log_func(u'{}\n{}'.format(title, msg)) 29 | if ABuEnv.g_is_mac_os: 30 | from ..UtilBu.ABuMacUtil import show_msg as do_show_msg 31 | else: 32 | from ..UtilBu.ABuWinUtil import show_msg as do_show_msg 33 | do_show_msg(title, msg) 34 | 35 | 36 | def socket_bind_recv(socket_fn, cmd_handler): 37 | """ 38 | 进程间socket或者共享内存通信,接受消息,处理消息,外层应处理catch_error 39 | :param socket_fn: socket文件名称或者共享内存名称 40 | :param cmd_handler: cmd处理函数,callable类型 41 | """ 42 | 43 | # TODO 使用ZeroMQ进行重新对接 44 | if ABuEnv.g_is_mac_os: 45 | from ..UtilBu.ABuMacUtil import socket_bind_recv as do_socket_bind_recv 46 | else: 47 | from ..UtilBu.ABuWinUtil import socket_bind_recv as do_socket_bind_recv 48 | do_socket_bind_recv(socket_fn, cmd_handler) 49 | 50 | 51 | def socket_send_msg(socket_fn, msg): 52 | """ 53 | 进程间socket或全局共享内通信,发送消息,外层应处理catch_error 54 | :param socket_fn: socket文件名称或者共享内存名称 55 | :param msg: 字符串类型需要传递的数据,不需要encode,内部进行encode 56 | """ 57 | # TODO 使用ZeroMQ进行重新对接 58 | if ABuEnv.g_is_mac_os: 59 | from ..UtilBu.ABuMacUtil import socket_send_msg as do_socket_send_msg 60 | else: 61 | from ..UtilBu.ABuWinUtil import socket_send_msg as do_socket_send_msg 62 | do_socket_send_msg(socket_fn, msg) 63 | 64 | 65 | @catch_error(return_val=0) 66 | def fold_free_size_mb(folder): 67 | """ 68 | 统一平路径可用空间获取,被catch_error装饰,即不应该被提示中断程序,return_val=0,出错也返回0 69 | :param folder: 路径或盘符信息 70 | :return: folder下的可用空间大小 71 | """ 72 | if ABuEnv.g_is_mac_os: 73 | from ..UtilBu.ABuMacUtil import fold_free_size_mb as do_fold_free_size_mb 74 | else: 75 | from ..UtilBu.ABuWinUtil import fold_free_size_mb as do_fold_free_size_mb 76 | do_fold_free_size_mb(folder) 77 | -------------------------------------------------------------------------------- /abupy/UtilBu/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from . import ABuDTUtil 4 | from . import ABuDelegateUtil 5 | from . import ABuDateUtil 6 | from . import ABuFileUtil 7 | from . import ABuMd5 8 | from . import ABuRegUtil 9 | from . import ABuScalerUtil 10 | from . import ABuStatsUtil 11 | from . import ABuStrUtil 12 | from . import ABuProgress 13 | from . import ABuPlatform 14 | from . import ABuKLUtil 15 | from . import ABuOsUtil 16 | 17 | from .ABuProgress import AbuProgress, AbuBlockProgress, AbuMulPidProgress 18 | 19 | __all__ = [ 20 | 'ABuDateUtil', 21 | 'ABuDelegateUtil', 22 | 'ABuDTUtil', 23 | 'ABuFileUtil', 24 | 'ABuMd5', 25 | 'ABuRegUtil', 26 | 'ABuScalerUtil', 27 | 'ABuStatsUtil', 28 | 'ABuStrUtil', 29 | 'ABuProgress', 30 | 'AbuProgress', 31 | 'AbuBlockProgress', 32 | 'AbuMulPidProgress', 33 | 'ABuPlatform', 34 | 'ABuKLUtil', 35 | 'ABuOsUtil' 36 | ] 37 | -------------------------------------------------------------------------------- /abupy/WidgetBu/ABuWGCrossVal.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | """策略相关性交叉验证图形可视化""" 3 | 4 | from __future__ import print_function 5 | from __future__ import absolute_import 6 | from __future__ import division 7 | 8 | import ipywidgets as widgets 9 | 10 | from ..WidgetBu.ABuWGBase import WidgetBase, show_msg_toast_func 11 | from ..WidgetBu.ABuWGBFBase import BuyFactorWGManager 12 | from ..WidgetBu.ABuWGSFBase import SellFactorWGManager 13 | # noinspection PyUnresolvedReferences 14 | from ..CoreBu.ABuFixes import filter 15 | from ..MetricsBu.ABuCrossVal import AbuCrossVal 16 | from ..CoreBu import ABuEnv 17 | from ..CoreBu.ABuEnv import EMarketTargetType 18 | 19 | __author__ = '阿布' 20 | __weixin__ = 'abu_quant' 21 | 22 | 23 | # noinspection PyProtectedMember 24 | class WidgetCrossVal(WidgetBase): 25 | """策略相关性交叉验证ui类""" 26 | 27 | # noinspection PyProtectedMember 28 | def __init__(self): 29 | """构建回测需要的各个组件形成tab""" 30 | 31 | tip_label1 = widgets.Label(u'策略相关性交叉验证暂不支持实时网络数据模式', layout=widgets.Layout(width='300px')) 32 | tip_label2 = widgets.Label(u'需先用\'数据下载界面操作\'进行下载', layout=widgets.Layout(width='300px')) 33 | 34 | self.bf = BuyFactorWGManager() 35 | self.sf = SellFactorWGManager(show_add_buy=True) 36 | 37 | sub_widget_tab = widgets.Tab() 38 | sub_widget_tab.children = [self.bf.widget, self.sf.widget] 39 | for ind, name in enumerate([u'买策', u'卖策']): 40 | sub_widget_tab.set_title(ind, name) 41 | 42 | self.begin_cross_val = widgets.Button(description=u'开始交叉相关性验证策略有效性', 43 | layout=widgets.Layout(width='98%'), 44 | button_style='danger') 45 | self.begin_cross_val.on_click(self.run_cross_val) 46 | 47 | self.market = widgets.Dropdown( 48 | options={u'美股': EMarketTargetType.E_MARKET_TARGET_US.value, 49 | u'A股': EMarketTargetType.E_MARKET_TARGET_CN.value, 50 | u'港股': EMarketTargetType.E_MARKET_TARGET_HK.value, 51 | u'国内期货': EMarketTargetType.E_MARKET_TARGET_FUTURES_CN.value, 52 | u'国际期货': EMarketTargetType.E_MARKET_TARGET_FUTURES_GLOBAL.value, 53 | u'数字货币': EMarketTargetType.E_MARKET_TARGET_TC.value}, 54 | value=ABuEnv.g_market_target.value, 55 | description=u'验证市场:', 56 | ) 57 | 58 | cv_label1 = widgets.Label(u'交叉验证的数量级:默认10', layout=widgets.Layout(width='300px')) 59 | cv_label2 = widgets.Label(u'cv次相关度范围随机抽取cv个symbol进行回测', layout=widgets.Layout(width='300px')) 60 | self.cv = widgets.IntSlider( 61 | value=10, 62 | min=4, 63 | max=50, 64 | step=1, 65 | description=u'cv', 66 | disabled=False, 67 | orientation='horizontal', 68 | readout=True, 69 | readout_format='d' 70 | ) 71 | cv_box = widgets.VBox([cv_label1, cv_label2, self.cv]) 72 | 73 | self.widget = widgets.VBox([tip_label1, tip_label2, sub_widget_tab, self.market, cv_box, 74 | self.begin_cross_val]) 75 | 76 | # 初始化就new处理,每次运行都使用它,可以缓存similar数据 77 | self.cross_val = AbuCrossVal() 78 | 79 | # noinspection PyUnusedLocal 80 | def run_cross_val(self, bt): 81 | """交叉相关性验证策略有效性的button按钮""" 82 | 83 | # 买入策略构成序列 84 | buy_factors = list(self.bf.factor_dict.values()) 85 | if len(buy_factors) == 0: 86 | show_msg_toast_func(u'请最少选择一个买入策略') 87 | return 88 | 89 | # 卖出策略可以一个也没有 90 | sell_factors = list(self.sf.factor_dict.values()) 91 | 92 | market = EMarketTargetType(self.market.value) 93 | self.cross_val.fit(buy_factors, sell_factors, cv=self.cv.value, market=market, ) 94 | -------------------------------------------------------------------------------- /abupy/WidgetBu/ABuWGDATool.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | """量化振幅分析工具图形可视化""" 3 | 4 | from __future__ import absolute_import 5 | from __future__ import division 6 | from __future__ import print_function 7 | 8 | import ipywidgets as widgets 9 | from IPython.display import display 10 | 11 | from ..UtilBu import ABuKLUtil 12 | from ..WidgetBu.ABuWGToolBase import WidgetToolBase, multi_fetch_symbol_analyse 13 | 14 | __author__ = '阿布' 15 | __weixin__ = 'abu_quant' 16 | 17 | 18 | # noinspection PyUnusedLocal 19 | class WidgetDATool(WidgetToolBase): 20 | """振幅分析界面""" 21 | 22 | def __init__(self, tool_set): 23 | """初始化数据分析界面""" 24 | super(WidgetDATool, self).__init__(tool_set) 25 | 26 | da_list = [] 27 | tip_label1 = widgets.Label(u'分析目标需要在\'分析设置\'中选择', layout=self.label_layout) 28 | tip_label2 = widgets.Label(u'需要设置多个分析目标进行对比', layout=self.label_layout) 29 | da_list.append(tip_label1) 30 | da_list.append(tip_label2) 31 | 32 | date_week_wave_bt = widgets.Button(description=u'交易日震幅对比分析', layout=widgets.Layout(width='98%'), 33 | button_style='info') 34 | date_week_wave_bt.on_click(self.date_week_wave) 35 | da_list.append(date_week_wave_bt) 36 | 37 | p_change_stats_bt = widgets.Button(description=u'交易日涨跌对比分析', layout=widgets.Layout(width='98%'), 38 | button_style='info') 39 | p_change_stats_bt.on_click(self.p_change_stats) 40 | da_list.append(p_change_stats_bt) 41 | 42 | wave_change_rate_bt = widgets.Button(description=u'振幅统计套利条件分析', layout=widgets.Layout(width='98%'), 43 | button_style='info') 44 | wave_change_rate_bt.on_click(self.wave_change_rate) 45 | da_list.append(wave_change_rate_bt) 46 | 47 | date_week_win_bt = widgets.Button(description=u'交易日涨跌概率分析', layout=widgets.Layout(width='98%'), 48 | button_style='info') 49 | date_week_win_bt.on_click(self.date_week_win) 50 | da_list.append(date_week_win_bt) 51 | 52 | bcut_change_vc_bt = widgets.Button(description=u'交易日涨跌区间分析(预定区间)', layout=widgets.Layout(width='98%'), 53 | button_style='info') 54 | bcut_change_vc_bt.on_click(self.bcut_change_vc) 55 | da_list.append(bcut_change_vc_bt) 56 | 57 | qcut_change_vc_bt = widgets.Button(description=u'交易日涨跌区间分析(不定区间)', layout=widgets.Layout(width='98%'), 58 | button_style='info') 59 | qcut_change_vc_bt.on_click(self.qcut_change_vc) 60 | da_list.append(qcut_change_vc_bt) 61 | 62 | self.widget = widgets.VBox(da_list, layout=widgets.Layout(width='58%')) 63 | 64 | @multi_fetch_symbol_analyse 65 | def qcut_change_vc(self, kl_dict, bt): 66 | """交易日涨跌区间分析(不定区间)action""" 67 | display(ABuKLUtil.qcut_change_vc(kl_dict)) 68 | 69 | @multi_fetch_symbol_analyse 70 | def bcut_change_vc(self, kl_dict, bt): 71 | """交易日涨跌区间分析(预定区间)action""" 72 | display(ABuKLUtil.bcut_change_vc(kl_dict)) 73 | 74 | @multi_fetch_symbol_analyse 75 | def date_week_win(self, kl_dict, bt): 76 | """交易日涨跌概率分析action""" 77 | display(ABuKLUtil.date_week_win(kl_dict)) 78 | 79 | @multi_fetch_symbol_analyse 80 | def wave_change_rate(self, kl_dict, bt): 81 | """振幅统计套利条件分析action""" 82 | ABuKLUtil.wave_change_rate(kl_dict) 83 | 84 | @multi_fetch_symbol_analyse 85 | def date_week_wave(self, kl_dict, bt): 86 | """交易日震幅对比分析action""" 87 | display(ABuKLUtil.date_week_wave(kl_dict)) 88 | 89 | @multi_fetch_symbol_analyse 90 | def p_change_stats(self, kl_dict, bt): 91 | """交易日涨跌对比分析action""" 92 | ABuKLUtil.p_change_stats(kl_dict) 93 | -------------------------------------------------------------------------------- /abupy/WidgetBu/ABuWGGridSearch.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | """策略最优参数grid search图形可视化""" 3 | 4 | from __future__ import print_function 5 | from __future__ import absolute_import 6 | from __future__ import division 7 | 8 | import ipywidgets as widgets 9 | 10 | from ..WidgetBu.ABuWGBase import WidgetBase, show_msg_toast_func 11 | from ..WidgetBu.ABuWGBSymbol import WidgetSymbolChoice 12 | from ..WidgetBu.ABuWGBFBase import BuyFactorWGManager 13 | from ..WidgetBu.ABuWGSFBase import SellFactorWGManager 14 | from ..CoreBu import ABuEnv 15 | # noinspection PyUnresolvedReferences 16 | from ..CoreBu.ABuFixes import filter 17 | from ..MarketBu.ABuDataCheck import check_symbol_data 18 | from ..MetricsBu.ABuGridSearch import GridSearch 19 | 20 | __author__ = '阿布' 21 | __weixin__ = 'abu_quant' 22 | 23 | 24 | # noinspection PyProtectedMember 25 | class WidgetGridSearch(WidgetBase): 26 | """策略最优参数grid search""" 27 | 28 | # noinspection PyProtectedMember 29 | def __init__(self): 30 | """构建回测需要的各个组件形成tab""" 31 | 32 | tip_label1 = widgets.Label(u'最优参数grid search暂不支持实时网络数据模式', layout=widgets.Layout(width='300px')) 33 | tip_label2 = widgets.Label(u'非沙盒模式需先用\'数据下载界面操作\'进行下载', layout=widgets.Layout(width='300px')) 34 | """沙盒数据与开放数据模式切换""" 35 | self.date_mode = widgets.RadioButtons( 36 | options=[u'沙盒数据模式', u'开放数据模式'], 37 | value=u'沙盒数据模式' if ABuEnv._g_enable_example_env_ipython else u'开放数据模式', 38 | description=u'数据模式:', 39 | disabled=False 40 | ) 41 | self.date_mode.observe(self.on_data_mode_change, names='value') 42 | date_mode_box = widgets.VBox([tip_label1, tip_label2, self.date_mode]) 43 | 44 | self.sc = WidgetSymbolChoice() 45 | self.bf = BuyFactorWGManager(add_button_style='grid') 46 | self.sf = SellFactorWGManager(show_add_buy=False, add_button_style='grid') 47 | 48 | sub_widget_tab = widgets.Tab() 49 | sub_widget_tab.children = [self.bf.widget, self.sf.widget, self.sc.widget] 50 | for ind, name in enumerate([u'买策', u'卖策', u'股池']): 51 | sub_widget_tab.set_title(ind, name) 52 | 53 | self.begin_grid_search = widgets.Button(description=u'开始寻找策略最优参数组合', layout=widgets.Layout(width='98%'), 54 | button_style='danger') 55 | self.begin_grid_search.on_click(self.run_grid_search) 56 | 57 | self.widget = widgets.VBox([date_mode_box, sub_widget_tab, self.begin_grid_search]) 58 | 59 | def on_data_mode_change(self, change): 60 | """沙盒与非沙盒数据界面操作转换""" 61 | if change['new'] == u'沙盒数据模式': 62 | ABuEnv.enable_example_env_ipython(show_log=False) 63 | else: 64 | # 从沙盒改变依然网络模式是本地模式 65 | ABuEnv._g_enable_example_env_ipython = False 66 | 67 | # noinspection PyUnusedLocal 68 | def run_grid_search(self, bt): 69 | """运行回测所对应的button按钮""" 70 | # 清理之前的输出结果 71 | # ABuProgress.clear_output() 72 | 73 | choice_symbols = self.sc.choice_symbols.options 74 | if choice_symbols is None or len(choice_symbols) == 0: 75 | # 如果一个symbol都没有设置None, gird search不支持全市场的最优参数寻找, 76 | show_msg_toast_func(u'请最少在\'股池\'中选择一个symbol!') 77 | return 78 | 79 | if not check_symbol_data(choice_symbols): 80 | # 监测是否本地缓存数据存在或者沙盒数据不匹配 81 | return 82 | 83 | # 买入策略构成序列 84 | buy_factors = list(self.bf.factor_dict.values()) 85 | if len(buy_factors) == 0: 86 | show_msg_toast_func(u'请最少选择一个买入策略') 87 | return 88 | # 合并买入因子不同的class factor到符合grid search格式的因子参数组合 89 | # print(buy_factors) 90 | buy_factors = GridSearch.combine_same_factor_class(buy_factors) 91 | 92 | # 卖出策略可以一个也没有 93 | sell_factors = list(self.sf.factor_dict.values()) 94 | # 合并卖出因子不同的class factor到符合grid search格式的因子参数组合 95 | sell_factors = GridSearch.combine_same_factor_class(sell_factors) 96 | 97 | scores, score_tuple_array = GridSearch.grid_search(choice_symbols, buy_factors, sell_factors) 98 | -------------------------------------------------------------------------------- /abupy/WidgetBu/ABuWGPosBase.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | """仓位资金管理参数以及选择图形可视化""" 3 | 4 | from __future__ import absolute_import 5 | from __future__ import division 6 | from __future__ import print_function 7 | 8 | from abc import abstractmethod 9 | 10 | import ipywidgets as widgets 11 | 12 | from ..WidgetBu.ABuWGBase import WidgetFactorBase, WidgetFactorManagerBase, accordion_shut 13 | from ..WidgetBu.ABuWGBFBase import BFSubscriberMixin 14 | 15 | __author__ = '阿布' 16 | __weixin__ = 'abu_quant' 17 | 18 | 19 | class PosWGManager(WidgetFactorManagerBase): 20 | """仓位资金管理组织类""" 21 | 22 | def __init__(self): 23 | super(PosWGManager, self).__init__() 24 | 25 | position_label = widgets.Label(u'无选定时默认资管为:atr资金仓位管理策略', 26 | layout=widgets.Layout(width='300px')) 27 | 28 | self.widget = widgets.VBox([self.factor_box, position_label, self.selected_factors]) 29 | 30 | def _init_widget(self): 31 | """构建内置的仓位资金管理可视化组件,构造出self.factor_box""" 32 | 33 | from ..WidgetBu.ABuWGPosition import AtrPosWidget, KellyPosWidget, PtPosition 34 | self.pos_array = [] 35 | self.pos_array.append(AtrPosWidget(self)) 36 | self.pos_array.append(KellyPosWidget(self)) 37 | self.pos_array.append(PtPosition(self)) 38 | 39 | # ps() call用widget组list 40 | children = [pos() for pos in self.pos_array] 41 | if self.scroll_factor_box: 42 | self.factor_box = widgets.Box(children=children, 43 | layout=self.factor_layout) 44 | else: 45 | # 一行显示两个,n个为一组,组装sub_children_group序列, 46 | sub_children_group = self._sub_children(children, len(children) / self._sub_children_group_cnt) 47 | sub_children_box = [widgets.HBox(sub_children) for sub_children in sub_children_group] 48 | self.factor_box = widgets.VBox(sub_children_box) 49 | # 买入因子是特殊的存在,都需要买入因子的全局数据 50 | self.buy_factor_manger = None 51 | 52 | def register(self, buy_factor_manger): 53 | """选股manager内部因子注册接收买入因子添加的改变""" 54 | self.buy_factor_manger = buy_factor_manger 55 | for ps in self.pos_array: 56 | self.buy_factor_manger.register_subscriber(ps) 57 | 58 | 59 | class WidgetPositionBase(WidgetFactorBase, BFSubscriberMixin): 60 | """仓位资金管理可视化基础类""" 61 | 62 | def __init__(self, wg_manager): 63 | super(WidgetPositionBase, self).__init__(wg_manager) 64 | self.add = widgets.Button(description=u'选定为全局资金管理策略', layout=widgets.Layout(width='98%'), 65 | button_style='info') 66 | # 选定全局资金管理略指令按钮 67 | self.add.on_click(self.add_position) 68 | # 运行混入的BFSubscriberMixin中ui初始化 69 | self.subscriber_ui([u'点击\'已添加的买入策略\'框中的买入策略', u'资金管理做为买入策略的资金管理策略']) 70 | # 买入策略框点击行为:将本卖出策略加到对应的买入策略做为附属 71 | self.buy_factors.observe(self.add_position_to_buy_factor, names='value') 72 | self.accordion.set_title(0, u'添加为指定买入因子的资金管理策略') 73 | accordion_shut(self.accordion) 74 | self.add_box = widgets.VBox([self.add, self.accordion]) 75 | 76 | # 具体子策略构建 77 | self._init_widget() 78 | 79 | @abstractmethod 80 | def _init_widget(self): 81 | """子类因子界面设置初始化""" 82 | pass 83 | 84 | @abstractmethod 85 | def make_position_unique(self): 86 | """ 87 | 子类因子构建唯一描述以及因子字典 88 | 返回值两个: 89 | 1. 因子构建字典对象 90 | 2. 因子唯一描述 91 | """ 92 | pass 93 | 94 | # noinspection PyUnusedLocal 95 | def add_position(self, bt): 96 | """对应按钮选定为全局仓位资金管理策略""" 97 | # 构建策略字典对象factor_dict以及唯一策略描述字符串factor_desc_key 98 | factor_dict, factor_desc_key = self.make_position_unique() 99 | self.wg_manager.add_factor(factor_dict, factor_desc_key, only_one=True) 100 | 101 | def add_position_to_buy_factor(self, select): 102 | """对应按钮添加策略到指定买入策略中""" 103 | self.add_to_buy_factor(select, self.make_position_unique, 'position', only_one=True) 104 | -------------------------------------------------------------------------------- /abupy/WidgetBu/ABuWGQuantTool.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | """量化技术分析工具图形可视化""" 3 | 4 | from __future__ import print_function 5 | from __future__ import absolute_import 6 | from __future__ import division 7 | 8 | import ipywidgets as widgets 9 | 10 | from ..WidgetBu.ABuWGBase import WidgetBase 11 | from ..WidgetBu.ABuWGToolBase import WidgetToolSet 12 | from ..WidgetBu.ABuWGTLTool import WidgetTLTool 13 | from ..WidgetBu.ABuWGDATool import WidgetDATool 14 | from ..WidgetBu.ABuWGSMTool import WidgetSMTool 15 | 16 | __author__ = '阿布' 17 | __weixin__ = 'abu_quant' 18 | 19 | 20 | class WidgetQuantTool(WidgetBase): 21 | """量化分析工具主界面""" 22 | 23 | def __init__(self): 24 | self.ts = WidgetToolSet() 25 | self.da = WidgetDATool(self.ts) 26 | self.tl = WidgetTLTool(self.ts) 27 | self.sm = WidgetSMTool(self.ts) 28 | sub_widget_tab = widgets.Tab() 29 | sub_widget_tab.children = [self.tl.widget, self.sm.widget, self.da.widget, self.ts.widget] 30 | for ind, name in enumerate([u'技术分析', u'相关分析', u'振幅分析', u'分析设置']): 31 | sub_widget_tab.set_title(ind, name) 32 | self.widget = widgets.VBox([sub_widget_tab]) 33 | -------------------------------------------------------------------------------- /abupy/WidgetBu/ABuWGVerifyTool.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | """策略验证工具图形可视化""" 3 | 4 | from __future__ import print_function 5 | from __future__ import absolute_import 6 | from __future__ import division 7 | 8 | import ipywidgets as widgets 9 | 10 | from ..WidgetBu.ABuWGBase import WidgetBase 11 | from ..WidgetBu.ABuWGGridSearch import WidgetGridSearch 12 | from ..WidgetBu.ABuWGCrossVal import WidgetCrossVal 13 | 14 | 15 | __author__ = '阿布' 16 | __weixin__ = 'abu_quant' 17 | 18 | 19 | class WidgetVerifyTool(WidgetBase): 20 | """策略验证工具主界面类实现""" 21 | 22 | def __init__(self): 23 | self.grid_search = WidgetGridSearch() 24 | self.cross_val = WidgetCrossVal() 25 | sub_widget_tab = widgets.Tab() 26 | sub_widget_tab.children = [self.grid_search.widget, self.cross_val.widget] 27 | for ind, name in enumerate([u'最优参数', u'交叉验证']): 28 | sub_widget_tab.set_title(ind, name) 29 | self.widget = widgets.VBox([sub_widget_tab]) 30 | -------------------------------------------------------------------------------- /abupy/WidgetBu/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from .ABuWGStockInfo import WidgetStockInfo, WidgetSearchStockInfo 4 | from .ABuWGBRunBase import WidgetRunTT 5 | from .ABuWGBSymbol import WidgetSymbolChoice 6 | from .ABuWGBRun import WidgetRunLoopBack 7 | from .ABuWGQuantTool import WidgetQuantTool 8 | from .ABuWGUpdate import WidgetUpdate 9 | from .ABuWGGridSearch import WidgetGridSearch 10 | from .ABuWGCrossVal import WidgetCrossVal 11 | from .ABuWGVerifyTool import WidgetVerifyTool 12 | 13 | __all__ = [ 14 | 'WidgetRunLoopBack', 15 | 'WidgetQuantTool', 16 | 17 | 'WidgetStockInfo', 18 | 'WidgetSearchStockInfo', 19 | 20 | 'WidgetRunTT', 21 | 'WidgetSymbolChoice', 22 | 'WidgetUpdate', 23 | 24 | 'WidgetGridSearch', 25 | 'WidgetCrossVal', 26 | 27 | 'WidgetVerifyTool' 28 | ] 29 | -------------------------------------------------------------------------------- /abupy/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | from __future__ import absolute_import 3 | 4 | from .CoreBu import * 5 | from .CheckBu import * 6 | from .FactorSellBu import * 7 | from .FactorBuyBu import * 8 | from .AlphaBu import * 9 | from .BetaBu import * 10 | from .DLBu import * 11 | from .IndicatorBu import * 12 | from .MLBu import * 13 | from .MetricsBu import * 14 | from .PickStockBu import * 15 | from .SlippageBu import * 16 | from .UtilBu import * 17 | from .TLineBu import * 18 | from .TradeBu import * 19 | from .UmpBu import * 20 | from .MarketBu import * 21 | from .SimilarBu import * 22 | from .WidgetBu import * 23 | 24 | __all__ = ['AlphaBu', 'BetaBu', 'CheckBu', 'UmpBu', 'FactorSellBu', 'FactorSell', 'IndicatorBu', 'MarketBu', 'UtilBu', 25 | 'SimilarBu', 'MetricsBu', 'SlippageBu', 'PickStockBu', 'CoreBu', 'TLineBu', 26 | 'MLBu', 'DLBu', 'TradeBu', 'WidgetBu'] 27 | 28 | __version__ = '0.4.0' 29 | __author__ = '阿布' 30 | __weixin__ = 'abu_quant' 31 | -------------------------------------------------------------------------------- /abupy_lecture/graphviz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/abupy_lecture/graphviz.png -------------------------------------------------------------------------------- /abupy_lecture/image/1.1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/abupy_lecture/image/1.1.png -------------------------------------------------------------------------------- /abupy_lecture/image/1.2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/abupy_lecture/image/1.2.png -------------------------------------------------------------------------------- /abupy_lecture/image/1.3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/abupy_lecture/image/1.3.png -------------------------------------------------------------------------------- /abupy_lecture/image/3.1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/abupy_lecture/image/3.1.png -------------------------------------------------------------------------------- /abupy_lecture/image/abu_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/abupy_lecture/image/abu_logo.png -------------------------------------------------------------------------------- /abupy_lecture/image/du_trend.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/abupy_lecture/image/du_trend.png -------------------------------------------------------------------------------- /abupy_lecture/image/f_trend.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/abupy_lecture/image/f_trend.png -------------------------------------------------------------------------------- /abupy_lecture/image/g_trend.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/abupy_lecture/image/g_trend.png -------------------------------------------------------------------------------- /abupy_lecture/image/gg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/abupy_lecture/image/gg.jpg -------------------------------------------------------------------------------- /abupy_lecture/image/mmm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/abupy_lecture/image/mmm.png -------------------------------------------------------------------------------- /abupy_lecture/image/pig3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/abupy_lecture/image/pig3.png -------------------------------------------------------------------------------- /abupy_lecture/image/pos_trend.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/abupy_lecture/image/pos_trend.png -------------------------------------------------------------------------------- /abupy_lecture/image/qrcode.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/abupy_lecture/image/qrcode.jpg -------------------------------------------------------------------------------- /abupy_lecture/image/run_ui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/abupy_lecture/image/run_ui.png -------------------------------------------------------------------------------- /abupy_lecture/image/save_cv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/abupy_lecture/image/save_cv.png -------------------------------------------------------------------------------- /abupy_lecture/image/st_mod.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/abupy_lecture/image/st_mod.png -------------------------------------------------------------------------------- /abupy_lecture/image/ump.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/abupy_lecture/image/ump.png -------------------------------------------------------------------------------- /abupy_lecture/image/ump_trade.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/abupy_lecture/image/ump_trade.png -------------------------------------------------------------------------------- /abupy_lecture/image/zsg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/abupy_lecture/image/zsg.jpg -------------------------------------------------------------------------------- /abupy_ui/gif/change_analyse.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/abupy_ui/gif/change_analyse.gif -------------------------------------------------------------------------------- /abupy_ui/gif/channel_line.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/abupy_ui/gif/channel_line.gif -------------------------------------------------------------------------------- /abupy_ui/gif/golden_line.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/abupy_ui/gif/golden_line.gif -------------------------------------------------------------------------------- /abupy_ui/gif/jump_line.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/abupy_ui/gif/jump_line.gif -------------------------------------------------------------------------------- /abupy_ui/gif/loop_back.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/abupy_ui/gif/loop_back.gif -------------------------------------------------------------------------------- /abupy_ui/gif/regress_line.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/abupy_ui/gif/regress_line.gif -------------------------------------------------------------------------------- /abupy_ui/gif/rs_line.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/abupy_ui/gif/rs_line.gif -------------------------------------------------------------------------------- /abupy_ui/gif/sd_line.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/abupy_ui/gif/sd_line.gif -------------------------------------------------------------------------------- /abupy_ui/gif/similar_line.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/abupy_ui/gif/similar_line.gif -------------------------------------------------------------------------------- /abupy_ui/gif/stock_info.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/abupy_ui/gif/stock_info.gif -------------------------------------------------------------------------------- /abupy_ui/gif/v_sense_line.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/abupy_ui/gif/v_sense_line.gif -------------------------------------------------------------------------------- /abupy_ui/readme.md: -------------------------------------------------------------------------------- 1 | ### 1. 历史回测界面操作 2 | ![](./gif/loop_back.gif) 3 | 4 | ### 2. 阻力位支撑位分析操作 5 | ![](./gif/rs_line.gif) 6 | 7 | ### 3. 跳空缺口分析筛选操作 8 | ![](./gif/jump_line.gif) 9 | 10 | ### 4. 趋势敏感速度对比操作 11 | ![](./gif/v_sense_line.gif) 12 | 13 | ### 5. 位移路程比分析操作 14 | ![](./gif/sd_line.gif) 15 | 16 | ### 6. 线性拟合分析操作 17 | ![](./gif/regress_line.gif) 18 | 19 | ### 7. 黄金分割分析操作 20 | ![](./gif/golden_line.gif) 21 | 22 | ### 8. 价格通道分析操作 23 | ![](./gif/channel_line.gif) 24 | 25 | ### 9. 相关性分析操作 26 | ![](./gif/similar_line.gif) 27 | 28 | ### 10. 涨跌幅分析操作 29 | ![](./gif/change_analyse.gif) 30 | 31 | 32 | ### 11. 股票基本信息查询界面 33 | ![](./gif/stock_info.gif) 34 | 35 | 36 | 更多abu量化教程请关注微信公众号: abu_quant 37 | 38 | ![](../abupy_lecture/image/qrcode.jpg) -------------------------------------------------------------------------------- /abupy_ui/run_cell.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/abupy_ui/run_cell.png -------------------------------------------------------------------------------- /abupy_ui/widget_base.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | from __future__ import print_function 3 | from __future__ import division 4 | 5 | from contextlib import contextmanager 6 | import os 7 | import sys 8 | import warnings 9 | 10 | sys.path.insert(0, os.path.abspath('../')) 11 | warnings.filterwarnings('ignore') 12 | warnings.simplefilter('ignore') 13 | 14 | 15 | @contextmanager 16 | def show_ui_ct(): 17 | print('正在初始化界面元素,请稍后...') 18 | from abupy import ABuStrUtil 19 | go_on = True 20 | 21 | try: 22 | if ABuStrUtil.str_is_cn(str(ABuStrUtil.__file__)): 23 | # 检测到运行环境路径中含有中文,严重错误,将出错,使用中文警告 24 | msg = u'严重错误!当前运行环境下有中文路径,abu将无法正常运行!请不要使用中文路径名称, 当前环境为{}'.format( 25 | ABuStrUtil.to_unicode(str(ABuStrUtil.__file__))) 26 | import logging 27 | logging.info(msg) 28 | go_on = False 29 | except: 30 | # 如果是其它编码的字符路径会进到这里 31 | import logging 32 | msg = 'error!non English characters in the current running environment,abu will not work properly!' 33 | logging.info(msg) 34 | go_on = False 35 | yield go_on 36 | 37 | if go_on: 38 | from IPython.display import clear_output 39 | clear_output() 40 | # import time 41 | # 这里sleep(0.3)防止有些版本clear_output把下面要展示的清除了,也不能使用clear_output的wait参数,有些浏览器卡死 42 | # time.sleep(0.3) 43 | -------------------------------------------------------------------------------- /abupy_ui/widget_loop_back.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | from __future__ import print_function 3 | from __future__ import division 4 | 5 | # 不要在abupy之外再建立包结构 6 | # noinspection PyUnresolvedReferences 7 | import widget_base 8 | 9 | 10 | def show_ui(): 11 | with widget_base.show_ui_ct() as go_on: 12 | if not go_on: 13 | return 14 | 15 | import abupy 16 | # check_cn=False因为上文已经check了 17 | abupy.env.enable_example_env_ipython(check_cn=False) 18 | from abupy import WidgetRunLoopBack 19 | widget = WidgetRunLoopBack() 20 | return widget() 21 | -------------------------------------------------------------------------------- /abupy_ui/widget_quant_tool.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | from __future__ import print_function 3 | from __future__ import division 4 | 5 | # 不要在abupy之外再建立包结构 6 | # noinspection PyUnresolvedReferences 7 | import widget_base 8 | 9 | 10 | def show_ui(): 11 | with widget_base.show_ui_ct() as go_on: 12 | if not go_on: 13 | return 14 | 15 | import abupy 16 | # check_cn=False因为上文已经check了 17 | abupy.env.enable_example_env_ipython(check_cn=False) 18 | from abupy import WidgetQuantTool 19 | widget = WidgetQuantTool() 20 | return widget() 21 | -------------------------------------------------------------------------------- /abupy_ui/widget_stock_info.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | from __future__ import print_function 3 | from __future__ import division 4 | 5 | # 不要在abupy之外再建立包结构 6 | # noinspection PyUnresolvedReferences 7 | import widget_base 8 | 9 | 10 | def show_ui(): 11 | with widget_base.show_ui_ct() as go_on: 12 | if not go_on: 13 | return 14 | from abupy import WidgetSearchStockInfo 15 | widget = WidgetSearchStockInfo() 16 | return widget() 17 | -------------------------------------------------------------------------------- /abupy_ui/widget_update_ui.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | from __future__ import print_function 3 | from __future__ import division 4 | 5 | # 不要在abupy之外再建立包结构 6 | # noinspection PyUnresolvedReferences 7 | import widget_base 8 | 9 | 10 | def show_ui(): 11 | with widget_base.show_ui_ct() as go_on: 12 | if not go_on: 13 | return 14 | from abupy import WidgetUpdate 15 | widget = WidgetUpdate() 16 | return widget() 17 | -------------------------------------------------------------------------------- /abupy_ui/widget_verify_tool.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | from __future__ import print_function 3 | from __future__ import division 4 | 5 | # 不要在abupy之外再建立包结构 6 | # noinspection PyUnresolvedReferences 7 | import widget_base 8 | 9 | 10 | def show_ui(): 11 | with widget_base.show_ui_ct() as go_on: 12 | if not go_on: 13 | return 14 | from abupy import WidgetVerifyTool 15 | widget = WidgetVerifyTool() 16 | return widget() 17 | -------------------------------------------------------------------------------- /abupy_ui/历史回测界面操作.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "### 点击上方的运行按钮,启动回测操作界面,如下图所示:\n", 8 | "\n", 9 | "![](./run_cell.png)" 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": null, 15 | "metadata": { 16 | "scrolled": false 17 | }, 18 | "outputs": [], 19 | "source": [ 20 | "%matplotlib inline\n", 21 | "import widget_loop_back\n", 22 | "widget_loop_back.show_ui()" 23 | ] 24 | }, 25 | { 26 | "cell_type": "markdown", 27 | "metadata": {}, 28 | "source": [ 29 | "[abu量化系统github地址](https://github.com/bbfamily/abu) (您的star是我的动力!)\n", 30 | "\n", 31 | "[更多阿布量化量化技术文章](http://www.abuquant.com/article)\n", 32 | "\n", 33 | "更多关于量化交易相关请阅读[《量化交易之路》](http://www.abuquant.com/books/quantify-trading-road.html)\n", 34 | "\n", 35 | "更多关于量化交易与机器学习相关请阅读[《机器学习之路》](http://www.abuquant.com/books/machine-learning-road.html)\n", 36 | "\n", 37 | "更多关于abu量化系统请关注微信公众号: abu_quant\n", 38 | "\n", 39 | "![](../abupy_lecture/image/qrcode.jpg)" 40 | ] 41 | } 42 | ], 43 | "metadata": { 44 | "kernelspec": { 45 | "display_name": "Python 3", 46 | "language": "python", 47 | "name": "python3" 48 | }, 49 | "language_info": { 50 | "codemirror_mode": { 51 | "name": "ipython", 52 | "version": 3 53 | }, 54 | "file_extension": ".py", 55 | "mimetype": "text/x-python", 56 | "name": "python", 57 | "nbconvert_exporter": "python", 58 | "pygments_lexer": "ipython3", 59 | "version": "3.6.1" 60 | } 61 | }, 62 | "nbformat": 4, 63 | "nbformat_minor": 2 64 | } 65 | -------------------------------------------------------------------------------- /abupy_ui/参数最优交叉验证.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "### 点击上方的运行按钮,启动回测操作界面,如下图所示:\n", 8 | "\n", 9 | "![](./run_cell.png)" 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": 1, 15 | "metadata": { 16 | "scrolled": false 17 | }, 18 | "outputs": [ 19 | { 20 | "data": { 21 | "application/vnd.jupyter.widget-view+json": { 22 | "model_id": "658d60448eb54362be4da65ff71b4880", 23 | "version_major": 2, 24 | "version_minor": 0 25 | }, 26 | "text/plain": [ 27 | "A Jupyter Widget" 28 | ] 29 | }, 30 | "metadata": {}, 31 | "output_type": "display_data" 32 | } 33 | ], 34 | "source": [ 35 | "%matplotlib inline\n", 36 | "import widget_verify_tool\n", 37 | "widget_verify_tool.show_ui()" 38 | ] 39 | }, 40 | { 41 | "cell_type": "markdown", 42 | "metadata": {}, 43 | "source": [ 44 | "[abu量化系统github地址](https://github.com/bbfamily/abu) (您的star是我的动力!)\n", 45 | "\n", 46 | "[更多阿布量化量化技术文章](http://www.abuquant.com/article)\n", 47 | "\n", 48 | "更多关于量化交易相关请阅读[《量化交易之路》](http://www.abuquant.com/books/quantify-trading-road.html)\n", 49 | "\n", 50 | "更多关于量化交易与机器学习相关请阅读[《机器学习之路》](http://www.abuquant.com/books/machine-learning-road.html)\n", 51 | "\n", 52 | "更多关于abu量化系统请关注微信公众号: abu_quant\n", 53 | "\n", 54 | "![](../abupy_lecture/image/qrcode.jpg)" 55 | ] 56 | }, 57 | { 58 | "cell_type": "code", 59 | "execution_count": null, 60 | "metadata": { 61 | "collapsed": true 62 | }, 63 | "outputs": [], 64 | "source": [] 65 | } 66 | ], 67 | "metadata": { 68 | "kernelspec": { 69 | "display_name": "Python 3", 70 | "language": "python", 71 | "name": "python3" 72 | }, 73 | "language_info": { 74 | "codemirror_mode": { 75 | "name": "ipython", 76 | "version": 3 77 | }, 78 | "file_extension": ".py", 79 | "mimetype": "text/x-python", 80 | "name": "python", 81 | "nbconvert_exporter": "python", 82 | "pygments_lexer": "ipython3", 83 | "version": "3.6.2" 84 | } 85 | }, 86 | "nbformat": 4, 87 | "nbformat_minor": 2 88 | } 89 | -------------------------------------------------------------------------------- /abupy_ui/数据下载界面操作.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "### 点击上方的运行按钮,启动回测操作界面,如下图所示:\n", 8 | "\n", 9 | "![](./run_cell.png)" 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": 4, 15 | "metadata": {}, 16 | "outputs": [ 17 | { 18 | "data": { 19 | "application/vnd.jupyter.widget-view+json": { 20 | "model_id": "54b6210ad8eb4103acf7880e2bb687f0" 21 | } 22 | }, 23 | "metadata": {}, 24 | "output_type": "display_data" 25 | } 26 | ], 27 | "source": [ 28 | "import widget_update_ui\n", 29 | "widget_update_ui.show_ui()" 30 | ] 31 | }, 32 | { 33 | "cell_type": "markdown", 34 | "metadata": {}, 35 | "source": [ 36 | "[abu量化系统github地址](https://github.com/bbfamily/abu) (您的star是我的动力!)\n", 37 | "\n", 38 | "[更多阿布量化量化技术文章](http://www.abuquant.com/article)\n", 39 | "\n", 40 | "更多关于量化交易相关请阅读[《量化交易之路》](http://www.abuquant.com/books/quantify-trading-road.html)\n", 41 | "\n", 42 | "更多关于量化交易与机器学习相关请阅读[《机器学习之路》](http://www.abuquant.com/books/machine-learning-road.html)\n", 43 | "\n", 44 | "更多关于abu量化系统请关注微信公众号: abu_quant\n", 45 | "\n", 46 | "![](../abupy_lecture/image/qrcode.jpg)" 47 | ] 48 | } 49 | ], 50 | "metadata": { 51 | "kernelspec": { 52 | "display_name": "Python 3", 53 | "language": "python", 54 | "name": "python3" 55 | }, 56 | "language_info": { 57 | "codemirror_mode": { 58 | "name": "ipython", 59 | "version": 3 60 | }, 61 | "file_extension": ".py", 62 | "mimetype": "text/x-python", 63 | "name": "python", 64 | "nbconvert_exporter": "python", 65 | "pygments_lexer": "ipython3", 66 | "version": "3.6.1" 67 | } 68 | }, 69 | "nbformat": 4, 70 | "nbformat_minor": 2 71 | } 72 | -------------------------------------------------------------------------------- /abupy_ui/股票基本信息查询.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "### 点击上方的运行按钮,启动回测操作界面,如下图所示:\n", 8 | "\n", 9 | "![](./run_cell.png)" 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": 3, 15 | "metadata": {}, 16 | "outputs": [ 17 | { 18 | "data": { 19 | "application/vnd.jupyter.widget-view+json": { 20 | "model_id": "2d38ed718ca24e81981d149d6371c3c0" 21 | } 22 | }, 23 | "metadata": {}, 24 | "output_type": "display_data" 25 | } 26 | ], 27 | "source": [ 28 | "import widget_stock_info\n", 29 | "widget_stock_info.show_ui()" 30 | ] 31 | }, 32 | { 33 | "cell_type": "markdown", 34 | "metadata": {}, 35 | "source": [ 36 | "[abu量化系统github地址](https://github.com/bbfamily/abu) (您的star是我的动力!)\n", 37 | "\n", 38 | "[更多阿布量化量化技术文章](http://www.abuquant.com/article)\n", 39 | "\n", 40 | "更多关于量化交易相关请阅读[《量化交易之路》](http://www.abuquant.com/books/quantify-trading-road.html)\n", 41 | "\n", 42 | "更多关于量化交易与机器学习相关请阅读[《机器学习之路》](http://www.abuquant.com/books/machine-learning-road.html)\n", 43 | "\n", 44 | "更多关于abu量化系统请关注微信公众号: abu_quant\n", 45 | "\n", 46 | "![](../abupy_lecture/image/qrcode.jpg)" 47 | ] 48 | } 49 | ], 50 | "metadata": { 51 | "kernelspec": { 52 | "display_name": "Python 3", 53 | "language": "python", 54 | "name": "python3" 55 | }, 56 | "language_info": { 57 | "codemirror_mode": { 58 | "name": "ipython", 59 | "version": 3 60 | }, 61 | "file_extension": ".py", 62 | "mimetype": "text/x-python", 63 | "name": "python", 64 | "nbconvert_exporter": "python", 65 | "pygments_lexer": "ipython3", 66 | "version": "3.6.1" 67 | } 68 | }, 69 | "nbformat": 4, 70 | "nbformat_minor": 2 71 | } 72 | -------------------------------------------------------------------------------- /abupy_ui/量化分析工具操作.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "### 点击上方的运行按钮,启动回测操作界面,如下图所示:\n", 8 | "\n", 9 | "![](./run_cell.png)" 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": 2, 15 | "metadata": { 16 | "scrolled": false 17 | }, 18 | "outputs": [ 19 | { 20 | "data": { 21 | "application/vnd.jupyter.widget-view+json": { 22 | "model_id": "aa1694ee35a14974adbd390537447cf9" 23 | } 24 | }, 25 | "metadata": {}, 26 | "output_type": "display_data" 27 | } 28 | ], 29 | "source": [ 30 | "%matplotlib inline\n", 31 | "import widget_quant_tool\n", 32 | "widget_quant_tool.show_ui()" 33 | ] 34 | }, 35 | { 36 | "cell_type": "markdown", 37 | "metadata": {}, 38 | "source": [ 39 | "[abu量化系统github地址](https://github.com/bbfamily/abu) (您的star是我的动力!)\n", 40 | "\n", 41 | "[更多阿布量化量化技术文章](http://www.abuquant.com/article)\n", 42 | "\n", 43 | "更多关于量化交易相关请阅读[《量化交易之路》](http://www.abuquant.com/books/quantify-trading-road.html)\n", 44 | "\n", 45 | "更多关于量化交易与机器学习相关请阅读[《机器学习之路》](http://www.abuquant.com/books/machine-learning-road.html)\n", 46 | "\n", 47 | "更多关于abu量化系统请关注微信公众号: abu_quant\n", 48 | "\n", 49 | "![](../abupy_lecture/image/qrcode.jpg)" 50 | ] 51 | } 52 | ], 53 | "metadata": { 54 | "kernelspec": { 55 | "display_name": "Python 3", 56 | "language": "python", 57 | "name": "python3" 58 | }, 59 | "language_info": { 60 | "codemirror_mode": { 61 | "name": "ipython", 62 | "version": 3 63 | }, 64 | "file_extension": ".py", 65 | "mimetype": "text/x-python", 66 | "name": "python", 67 | "nbconvert_exporter": "python", 68 | "pygments_lexer": "ipython3", 69 | "version": "3.6.1" 70 | } 71 | }, 72 | "nbformat": 4, 73 | "nbformat_minor": 2 74 | } 75 | -------------------------------------------------------------------------------- /gen/stock_day_change.npy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/gen/stock_day_change.npy -------------------------------------------------------------------------------- /img/abu_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/img/abu_logo.png -------------------------------------------------------------------------------- /img/d2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/img/d2.png -------------------------------------------------------------------------------- /img/d3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/img/d3.png -------------------------------------------------------------------------------- /img/fl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/img/fl.png -------------------------------------------------------------------------------- /img/head.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/img/head.png -------------------------------------------------------------------------------- /img/img1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/img/img1.png -------------------------------------------------------------------------------- /img/img10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/img/img10.png -------------------------------------------------------------------------------- /img/img11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/img/img11.png -------------------------------------------------------------------------------- /img/img12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/img/img12.png -------------------------------------------------------------------------------- /img/img13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/img/img13.png -------------------------------------------------------------------------------- /img/img14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/img/img14.png -------------------------------------------------------------------------------- /img/img2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/img/img2.png -------------------------------------------------------------------------------- /img/img3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/img/img3.png -------------------------------------------------------------------------------- /img/img4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/img/img4.png -------------------------------------------------------------------------------- /img/img5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/img/img5.png -------------------------------------------------------------------------------- /img/img6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/img/img6.png -------------------------------------------------------------------------------- /img/img7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/img/img7.png -------------------------------------------------------------------------------- /img/img8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/img/img8.png -------------------------------------------------------------------------------- /img/img9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/img/img9.png -------------------------------------------------------------------------------- /img/qrcode.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/img/qrcode.jpg -------------------------------------------------------------------------------- /img/quant_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/img/quant_icon.png -------------------------------------------------------------------------------- /ipython/readme.md: -------------------------------------------------------------------------------- 1 | # 量化交易之路 ipython代码 2 | 3 | 1. [第二章 量化语言——Python](https://github.com/bbfamily/abu/tree/master/ipython/第二章-量化语言——Python.ipynb) 4 | 2. [第三章 量化工具——NumPy](https://github.com/bbfamily/abu/tree/master/ipython/第三章-量化工具——NumPy.ipynb) 5 | 3. [第四章 量化工具——pandas](https://github.com/bbfamily/abu/tree/master/ipython/第四章-量化工具——pandas.ipynb) 6 | 4. [第五章 量化工具——可视化](https://github.com/bbfamily/abu/tree/master/ipython/第五章-量化工具——可视化.ipynb) 7 | 5. [第六章 量化工具——数学:你一生的追求到底能带来多少幸福](https://github.com/bbfamily/abu/tree/master/ipython/第六章-量化工具——数学.ipynb) 8 | 6. [第七章 量化系统——入门:三只小猪股票投资的故事](https://github.com/bbfamily/abu/tree/master/ipython/第七章-量化系统——入门.ipynb) 9 | 7. [第八章 量化系统——开发](https://github.com/bbfamily/abu/tree/master/ipython/第八章-量化系统——开发.ipynb) 10 | 8. [第九章 量化系统——度量与优化](https://github.com/bbfamily/abu/tree/master/ipython/第九章-量化系统——度量与优化.ipynb) 11 | 9. [第十章 量化系统——机器学习•猪老三](https://github.com/bbfamily/abu/tree/master/ipython/第十章-量化系统——机器学习•猪老三.ipynb) 12 | 10. [第十一章 量化系统——机器学习•ABU](https://github.com/bbfamily/abu/tree/master/ipython/第十一章-量化系统——机器学习•ABU.ipynb) 13 | 11. [附录A 量化环境部署](https://github.com/bbfamily/abu/tree/master/ipython/附录A-量化环境部署.ipynb) 14 | 12. [附录B 量化相关性分析](https://github.com/bbfamily/abu/tree/master/ipython/附录B-量化相关性分析.ipynb) 15 | 13. [附录C 量化统计分析及指标应用](https://github.com/bbfamily/abu/tree/master/ipython/附录C-量化统计分析及指标应用.ipynb) 16 | -------------------------------------------------------------------------------- /python/abu_local_env.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | import os 3 | import sys 4 | 5 | sys.path.append(os.path.abspath('../')) 6 | -------------------------------------------------------------------------------- /python/extA.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | from __future__ import print_function 3 | import seaborn as sns 4 | import warnings 5 | 6 | # noinspection PyUnresolvedReferences 7 | import abu_local_env 8 | import abupy 9 | from abupy import ABuSymbolPd 10 | from abupy import EMarketSourceType 11 | from abupy import EMarketDataFetchMode 12 | from abupy import AbuFactorBuyBreak 13 | from abupy import AbuFactorAtrNStop 14 | from abupy import AbuFactorPreAtrNStop 15 | from abupy import AbuFactorCloseAtrNStop 16 | from abupy import AbuMetricsBase 17 | from abupy import abu 18 | 19 | warnings.filterwarnings('ignore') 20 | sns.set_context(rc={'figure.figsize': (14, 7)}) 21 | 22 | # 设置选股因子,None为不使用选股因子 23 | stock_pickers = None 24 | # 买入因子依然延用向上突破因子 25 | buy_factors = [{'xd': 60, 'class': AbuFactorBuyBreak}, 26 | {'xd': 42, 'class': AbuFactorBuyBreak}] 27 | # 卖出因子继续使用上一章使用的因子 28 | sell_factors = [ 29 | {'stop_loss_n': 1.0, 'stop_win_n': 3.0, 30 | 'class': AbuFactorAtrNStop}, 31 | {'class': AbuFactorPreAtrNStop, 'pre_atr_n': 1.5}, 32 | {'class': AbuFactorCloseAtrNStop, 'close_atr_n': 1.5} 33 | ] 34 | 35 | """ 36 | 附录A 量化环境部署 37 | 38 | abu量化系统github地址:https://github.com/bbfamily/abu (您的star是我的动力!) 39 | abu量化文档教程ipython notebook:https://github.com/bbfamily/abu/tree/master/abupy_lecture 40 | 41 | * 本节建议对照阅读abu量化文档: 第19节 数据源 42 | """ 43 | 44 | 45 | def sample_a21(): 46 | """ 47 | A.2.1 数据模式的切换 48 | :return: 49 | """ 50 | # 表A-1所示 51 | print(ABuSymbolPd.make_kl_df('601398').tail()) 52 | 53 | # 局部使用enable_example_env_ipython,示例 54 | abupy.env.enable_example_env_ipython() 55 | # 如果本地有相应股票的缓存,可以使用如下代码强制使用本地缓存数据 56 | # abupy.env.g_data_fetch_mode = EMarketDataFetchMode.E_DATA_FETCH_FORCE_LOCAL 57 | 58 | # 设置初始资金数 59 | read_cash = 1000000 60 | 61 | # 择时股票池 62 | choice_symbols = ['usNOAH', 'usSFUN', 'usBIDU', 'usAAPL', 'usGOOG', 'usTSLA', 'usWUBA', 'usVIPS'] 63 | # 使用run_loop_back运行策略 64 | abu_result_tuple, _ = abu.run_loop_back(read_cash, 65 | buy_factors, sell_factors, stock_pickers, choice_symbols=choice_symbols, 66 | n_folds=2) 67 | metrics = AbuMetricsBase(*abu_result_tuple) 68 | metrics.fit_metrics() 69 | metrics.plot_returns_cmp() 70 | 71 | # ***************************************************************************************************************** 72 | # 切换数据源 73 | abupy.env.g_market_source = EMarketSourceType.E_MARKET_SOURCE_tx 74 | # 强制走网络数据源 75 | abupy.env.g_data_fetch_mode = EMarketDataFetchMode.E_DATA_FETCH_FORCE_NET 76 | # 择时股票池 77 | choice_symbols = ['601398', '600028', '601857', '601318', '600036', '000002', '600050', '600030'] 78 | # 使用run_loop_back运行策略 79 | abu_result_tuple, _ = abu.run_loop_back(read_cash, 80 | buy_factors, sell_factors, stock_pickers, choice_symbols=choice_symbols, 81 | n_folds=2) 82 | 83 | metrics = AbuMetricsBase(*abu_result_tuple) 84 | metrics.fit_metrics() 85 | metrics.plot_returns_cmp() 86 | 87 | 88 | """ 89 | A.2.2 目标市场的切换 90 | A.2.3 A股市场的回测示例 91 | 92 | * 相关内容请阅读abu量化文档:第8节 A股市场的回测, 第20节 A股全市场回测 93 | """ 94 | 95 | """ 96 | A.2.4 港股市场的回测示例 97 | 98 | * 相关内容请阅读abu量化文档:第9节 港股市场的回测 99 | """ 100 | 101 | if __name__ == "__main__": 102 | sample_a21() 103 | # sample_a23_1() 104 | # sample_a23_2() 105 | # sample_a23_2(from_cache=True) 106 | # sample_a24_1() 107 | # sample_a24_2() 108 | # sample_a24_2(from_cache=True) 109 | -------------------------------------------------------------------------------- /python/extC.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | from __future__ import print_function 3 | import seaborn as sns 4 | import warnings 5 | 6 | # noinspection PyUnresolvedReferences 7 | import abu_local_env 8 | import abupy 9 | from abupy import EStoreAbu, abu 10 | from abupy import ABuSymbolPd 11 | from abupy import tl 12 | from abupy import nd 13 | from abupy import ABuMarketDrawing 14 | 15 | warnings.filterwarnings('ignore') 16 | sns.set_context(rc={'figure.figsize': (14, 7)}) 17 | 18 | """ 19 | 附录C-量化统计分析及指标应用 20 | 21 | abu量化系统github地址:https://github.com/bbfamily/abu (您的star是我的动力!) 22 | abu量化文档教程ipython notebook:https://github.com/bbfamily/abu/tree/master/abupy_lecture 23 | 24 | 本节内容建议对照阅读abu量化文档:第13节 量化技术分析应用 25 | """ 26 | 27 | 28 | def sample_c1(): 29 | """ 30 | C.1 量化统计分析应用 31 | :return: 32 | """ 33 | tsla_df = ABuSymbolPd.make_kl_df('usTSLA', n_folds=2) 34 | 35 | jumps = tl.jump.calc_jump(tsla_df) 36 | print('jumps:\n', jumps) 37 | 38 | # sw[0]代表非时间因素的jump_power,sw[1]代表时间加权因素的jump_power,当sw[0]=1时与非加权方式相同,具体实现请参考源代码 39 | filter_jumps = tl.jump.calc_jump_line_weight(tsla_df, sw=(0.5, 0.5)) 40 | print('filter_jumps:\n', filter_jumps) 41 | 42 | # tl.wave.calc_wave_abs()函数可视化价格波动情况 43 | tl.wave.calc_wave_abs(tsla_df, xd=21, show=True) 44 | 45 | 46 | """ 47 | C.2 量化技术指标应用: 对量化策略失败结果的人工分析 48 | """ 49 | 50 | 51 | def sample_c2(): 52 | """ 53 | C.2 量化技术指标应用: 对量化策略失败结果的人工分析 54 | :return: 55 | """ 56 | abupy.env.disable_example_env_ipython() 57 | 58 | # 从之前章节的缓存中读取交易数据 59 | abu_result_tuple_train = abu.load_abu_result_tuple(n_folds=5, store_type=EStoreAbu.E_STORE_CUSTOM_NAME, 60 | custom_name='train_cn') 61 | # 只筛选orders中有交易结果的单子 62 | has_result = abu_result_tuple_train.orders_pd[ 63 | abu_result_tuple_train.orders_pd.result == -1] 64 | 65 | # 随便拿一个交易数据作为示例 66 | sample_order = has_result.ix[100] 67 | _ = ABuMarketDrawing.plot_candle_from_order(sample_order) 68 | 69 | nd.macd.plot_macd_from_order(sample_order, date_ext=252) 70 | nd.boll.plot_boll_from_order(has_result.ix[100], date_ext=252) 71 | nd.ma.plot_ma_from_order(has_result.ix[100], date_ext=252, time_period=[10, 20, 30, 60, 90, 120]) 72 | 73 | 74 | if __name__ == "__main__": 75 | sample_c1() 76 | # sample_c2() 77 | -------------------------------------------------------------------------------- /python/graphviz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbfamily/abu/6b1f3005288a063341806fa26254d799dde042a6/python/graphviz.png -------------------------------------------------------------------------------- /python/readme.md: -------------------------------------------------------------------------------- 1 | # 量化交易之路 python代码 2 | 3 | 4 | 提供了python版本的代码示例实现,但请尽量能熟练使用notebook,使用了交互式操作的ipython notebook便于量化交易策略的思路快速实现,检验,面向过程的步骤,强大的可视化内嵌进一步引导思路,方便将零散的思路一点一点变成代码,验证代码的有效性,以及更多的实验特性 5 | 6 | 1. [第二章 量化语言——Python]() 7 | 2. [第三章 量化工具——NumPy]() 8 | 3. [第四章 量化工具——pandas]() 9 | 4. [第五章 量化工具——可视化]() 10 | 5. [第六章 量化工具——数学:你一生的追求到底能带来多少幸福]() 11 | 6. [第七章 量化系统——入门:三只小猪股票投资的故事]() 12 | 7. [第八章 量化系统——开发]() 13 | 8. [第九章 量化系统——度量与优化]() 14 | 9. [第十章 量化系统——机器学习•猪老三]() 15 | 10. [第十一章 量化系统——机器学习•ABU]() 16 | 11. [附录A 量化环境部署]() 17 | 12. [附录B 量化相关性分析]() 18 | 13. [附录C 量化统计分析及指标应用]() -------------------------------------------------------------------------------- /界面操作视频教程/第26节星期几是这个股票的好日子界面操作视频.md: -------------------------------------------------------------------------------- 1 | 2 | # ABU量化界面操作示例 3 | 4 | 5 | ----------------- 6 | 7 | ## 第26节 星期几是这个股票的‘好日子’ 8 | 9 | 本节将示例一个与周期相关的短线择时策略,本节的内容是为《量化交易之路》中的一个小节做的完整策略实例补充。 10 | 11 | 12 | [视频教程播放地址](https://v.qq.com/x/page/l0556oqgemk.html) 13 | 14 | 15 | [项目github地址](https://github.com/bbfamily/abu) 16 | 17 | ------------------------------------------ 18 | 19 | 很多刚接触交易的人总喜欢把交易看成一种有固定收入的工作,比如他们有自己的规矩,周五一定要把所有股票都卖了,安安心心过周末,周一看情况一切良好再把股票买回来。 20 | 21 | 还有一些人有着很奇怪的癖好认为周三是他的幸运日,在周三买入他选中的股票,有些人每个月第一个周五发工资,市场就是由这些各种各样的人组成的。 22 | 23 | ------------------------------------------ 24 | 25 | 某一个股票上的活跃用户在一段短时间内变化并不大,也就是说这些习惯周五卖周一买的人会反复在一支股票上交易,普通投资者普遍的投资方式是针对一支股票不断的进行买卖,他们不会长期持有这支股票,但也不会远离这支股票很长时间,我认为有两点促成了以上事实。 26 | 27 | 1. 贪欲:贪欲在这中间起到了很大的作用,当一个人第一次买入一支股票并且持有到有一定利润的时候,他选择卖出这支股票,因为他认为涨的已经很多了,该适当的回调了,之后股价的走势只有两种可能:第一按照他的预期下跌,这样的话他可能选择跌到某种程度再次进场买入这支股票;第二就是继续上涨,这种情况下他会选择不断‘诅咒’这支股票,直到有一天股价上涨到让他无法忍受,从此由‘黑转粉’。 28 | 29 | 2. 时间成本与懒惰:一个人类的时间和精力都是有限的,它无法获取市场中所有股票的信息,每次获取熟悉一支股票的时间成本在他看来也是非常巨大,他反复的盯着自己最频繁买卖的那几支股票。 30 | 31 | 下面首先针对沙盒数据中的美股分析一年内的‘周几'涨跌概率 32 | 33 |
34 | 35 | ## 交易日涨跌概率分析 36 | 37 | 一个一个观察每一个股票的周期涨跌概率,可以发现: 38 | 39 | 1. 特斯拉在周四上涨的概率最大59% 40 | 2. 诺亚财富也在周四上涨的概率最大65% 41 | 3. 百度在周五上涨概率达到60% 42 | 4. 苹果在周三上涨概率达到56% 43 | 44 |
45 | 46 | ## 日胜率均值回复策略 47 | 48 | 策略大概原理如下: 49 | 50 | 策略的性质属于:**均值回复** 51 | 52 | 1. 默认以40天为周期(8周)结合涨跌阀值计算周几适合买入 53 | 2. 回测运行中每一个月重新计算一次上述的周几适合买入 54 | 3. 在策略日任务中买入信号为:昨天下跌,今天开盘也下跌,且明天是计算出来的上涨概率大的'周几' 55 | 56 | 下面开始分市场使用策略进行历史回测: 57 | 58 | 1. 使用沙盒数据中的美股symbol作为买入目标 59 | 2. 买入策略使用:日胜率均值回复策略 60 | 3. 卖出策略使用:持有N天后卖出策略(n=1)持有一天后当天卖出 61 | 62 |
63 | _____ 64 | 65 | 可以看到上面的回测中胜率超过了50%,交易单中可以看到所有交易都只持有了一天 66 | 67 | 上面的策略中计算'周几'上涨概率最大的交易周期默认为40天周期(8周),这个周期长度不能太长也不能太短,因为某一个股票上的活跃用户只是在一段短时间内变化不大,但是**一个市场中的参与者随着时间的流逝,也在慢慢不断变化,不断新老交替,就像我们人类,每7年我们就是一个全新的自己,所有细胞血液都将完全更新一遍**。 68 | 69 | 下面使用这个策略对**比特币,莱特币**进行回测 70 | 71 |
72 | ____ 73 | ## 日胜率均值回复策略A股市场回测 74 | 下面使用这个沙盒中**A股市场**symbol进行回测: 75 |
76 | 77 | ____ 78 | 79 | 小结: 80 | 81 | 上面的回测交易由于使用沙盒数据,数据量少,所以实际上的回测效果一般,即如果一个策略有56%的胜率,那么一天只执行10次交易,你的胜率有各种可能,不一定达到56%,但是如果你能一天执行10000次以上,那么你的胜率如果不是56%,不管是更多或者更少,都代表你计算胜率的方式有问题。 82 | 83 | 所以针对上面这个策略,确定你拥有交易概率优势,只要一天内可以从不同市场、不同股票、不同时段内找到足够多的交易机会,执行足够多的次数,那你最后一定是盈利的,统计套利的核心思想就是这个,不只是要单纯追求胜率,更应该关注大数定律,寻找多元化的交易机会,最终达成理想的胜率。 84 | 85 | 在之后的章节中会示例不使用沙盒数据,在各个市场中通过这个策略寻找交易进行进行回测,请关注公众号中的代码示例更新 86 | 87 |
88 |
89 |
-------------------------------------------------------------------------------- /界面操作视频教程/第一节界面操作视频教程.md: -------------------------------------------------------------------------------- 1 | 2 | # ABU量化界面操作示例 3 | 4 | 5 | ----------------- 6 | 7 | ## 第1节 择时策略的开发 & 第2节 择时策略的优化 8 | 9 | 10 | [视频播放地址](https://v.qq.com/x/page/g0555b9k6ge.html) 11 | 12 | 13 | [项目github地址](https://github.com/bbfamily/abu) 14 | 15 | ------------------------------------------ 16 | 17 | 量化系统一般分为回测模块、实盘模块。 18 | 19 | * 回测模块:首先交易者编写实现一个交易策略,它基于一段历史的交易数据,根据交易策略进行模拟买入卖出,策略中可以涉及买入规则、卖出规则、选股规则、仓位控制及滑点策略等等,回测的目的是验证交易策略是否可行。 20 | * 实盘模块:将回测通过的策略应用于每天的实时交易数据,根据策略发出买入信号、卖出信号,进行实际的买入、卖出操作。 21 | 22 | 回测模块最重要的组成部份是择时、选股: 23 | 24 | * 择时(什么时候投资) 25 | * 选股(投资什么股票) 26 | 27 | 只有在对的时间买入对的股票才能获利,就像下面张小娴的名言一样,可以把‘股票’ 代替 ‘人’完全合乎逻辑。 28 | 29 | >在对的时间,遇见对的人(股票),是一种幸福 30 | > 31 | >在对的时间,遇见错的人(股票),是一种悲伤 32 | > 33 | >在错的时间,遇见对的人(股票),是一声叹息 34 | > 35 | >在错的时间,遇见错的人(股票),是一种无奈 36 | 37 | 海龟交易法则是量化经典书籍中的经典作品,它里面介绍过一种趋势跟踪策略:N日趋势突破策略 38 | 39 | 趋势突破定义为当天收盘价格超过N天内的最高价或最低价,超过最高价格作为买入信号买入股票持有,超过最低价格作为卖出信号。 40 | 41 | 下面演示使用: 42 | 43 | * 初始回测资金设置1000000 44 | * 使用特斯拉(TSLA)做为买入选股目标 45 | * 海龟向上突破42d做为买入策略 46 | * 海龟向上突破60d做为买入策略 47 | 48 | ----------------- 49 | 50 | ### 1 基本止盈止损策略 51 | 52 | 量化交易系统一般都会有止盈策略和止损策略。 53 | 54 | 下面使用: 55 | 56 | * 止盈止损策略 57 | * 海龟向下突破120d 58 | 59 | 两个卖出因子策略并行同时生效做为示例 60 | 61 | 真实波幅atr作为最大止盈和最大止损的常数值: 62 | 63 | * 当stop_loss_n 乘以 当日atr > 买入价格 - 当日收盘价格:止损卖出,如下止损n = 0.5 64 | * 当stop_win_n 乘以 当日atr < 当日收盘价格 -买入价格:止盈卖出,如下止盈n = 3.0 65 | 66 | 67 | 68 | 69 | ### 2. 风险控制止损策略 70 | 71 | 效果比之前好多了,下面再加入一些其它卖出策略,量化交易系统中一般都会有风险控制策略,比如当股票今天价格开始剧烈下跌,采取果断平仓措施。 72 | 73 | 下面使用: 74 | 75 | * 风险止损策略 76 | * 止盈止损策略 77 | * 海龟向下突破120d 78 | 79 | 三个卖出因子策略并行同时生效做为示例 80 | 81 | 风险止损策略中继续使用真实波幅atr作为常数值: 82 | 83 | 当今日价格下跌幅度 > 当日atr 乘以 pre_atr_n(下跌止损倍数)卖出股票, 本例使用pre_atr_n=1.0 84 | 85 | ### 3. 利润保护止盈策略 86 | 87 | 接下来注意下图这笔交易,会发现本来有很多盈利的,但是由于止盈没有达到,所以最后变成了亏损 88 | 89 | ![](../abupy_lecture/image/1.3.png) 90 | 91 | 可以通过添加保护盈利的卖出因子来使上图那笔交易获利 92 | 93 | 下面使用: 94 | 95 | * 保护盈利策略 96 | * 风险止损策略 97 | * 止盈止损策略 98 | * 海龟向下突破120d 99 | 100 | 4个卖出因子策略并行同时生效做为示例 101 | 102 | atr移动止盈策略,当买入股票有一定收益后,如果股价下跌幅度超过close_atr_n乘以当日atr, 则保护止盈卖出,如下示例使用close_atr_n=1.5 103 | 104 | 从交易结果可以看到最终那笔失败的交易也盈利卖出了。 105 | 106 | 注意:上面的很多拟合优化操作在实际应用中是不可取的,比如最后的那个使用AbuFactorCloseAtrNStop使交易盈利以及我之后即将讲解的另一些手段使整体交易变好的做法,不应该因为某些特定股票或者特定交易修改参数或者添加因子等方式使结果变好,这样就是过拟合择时交易系统,将会在下一章节来示例如何挑选参数及因子的选择问题,本节内容主要是为了讲解择时系统的示例。 107 | 108 | 109 | 更多关于abu量化系统请关注微信公众号: abu_quant 110 | 111 | [abu项目开源地址](https://github.com/bbfamily/abu) 112 | 113 | [阿布量化网站地址](http://abuquant.com) 114 | 115 | ![](../abupy_lecture/image/qrcode.jpg) 116 | --------------------------------------------------------------------------------