1.OCå
å管ç-runloop
2.Backtrader来啦:可视化篇(重构)
3.LiveDataBus
OCå å管ç-runloop
RunLoop æ¯éè¿å é¨ç»´æ¤ç äºä»¶å¾ªç¯( Event Loop )æ¥å¯¹ äºä»¶/æ¶æ¯è¿è¡ç®¡ççä¸ä¸ªå¯¹è±¡ãrunloop çå®æ¹ææ¡£å¨ thread ç¯ç« Run Loops ï¼ä¹å°±ä»ä¾§é¢è¯´æäº runloop æ¯ä¸çº¿ç¨æ¯æ¯ç¸å ³çã
å®æ¹æå¦ä¸ä¸å¼ å¾ï¼
线ç¨çè¾å ¥æº:
线ç¨é对è¾å ¥æºçå¤çæºå¶ï¼
æ以ä¸æ¡ä¾ï¼
timer ä¸ performSelector 对åºçåè°é½æ¯ __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ ï¼
block å¯¹åº __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ ï¼
主线ç¨å¯¹åº __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ :
ç³»ç»è§¦æ¸äºä»¶å¯¹åº __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ ï¼
éç¥äºä»¶å¯¹åº __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ ï¼
å°ç»ï¼
æ»å¨é¡µé¢è¾åºï¼
页é¢æ»å¨è¿ç¨ä¸å¤äº UITrackingRunLoopMode ï¼éæ¢ç¶æå¤äº kCFRunLoopDefaultMode ã
è¾åºï¼
è¾åºï¼
æ¢ç¶ runloop æ¯ä¸ä¸ªäºä»¶å¾ªç¯ï¼é£ä¹å®ä¸æ®éç循ç¯æä»ä¹åºå«å¢ï¼
æ®é循ç¯ï¼
runloop 循ç¯ï¼
é£ä¹å¯ä»¥å¾å°ä»¥ä¸ç»è®ºï¼
é£ä¹ runloop æ¯æä¹åå°çå¢ï¼
é常æ们ä¼éè¿ NSRunLoop å»è·åå½åç runloop ï¼
å®ä¹å¦ä¸ï¼
ç» currentRunLoop ä¸ç¬¦å·æç¹ï¼
éè¿ä¹åçåæå·²ç»å®ä½å°äº runloop æ¯å¨ CoreFoundation ä¸ç CoreFoundationæºç ãæ£å¥½ CoreFoundation å¼æºäº CFRunLoop ï¼
é£ä¹æ ¸å¿é»è¾å°±å¨ CFRunLoopRunSpecific ä¸ãè¿æä¸ä¸ªçé®æ¯ runloop å¯ä»¥ä¼ç ï¼é£ä¹å®æ¯å¦ä½å®ç°çå¢ï¼
è¦äºè§£ runloop çå®ç°åçï¼é¦å è¦æ¸ æ¥å®çæ°æ®ç»æã
CFRunLoopRunSpecific ç第ä¸ä¸ªåæ°æ¯ CFRunLoopGetCurrent() ï¼
_CFRunLoopGet0
CFRunLoopRef çå®ä¹å¦ä¸ï¼
å®é ä¸åºå±å®æ¯ __CFRunLoop ç±»åï¼
å¯¹äº timer èè¨:
æ¾ç¶å®æ¯è¦ä¾èµ mode çã
CFRunLoopMode
èä¸ä¸ª mode ä¸å对åºå¤ä¸ª items(source0ãsource1ãtimersãobservers) ï¼æ以就æå¦ä¸å ³ç³»ï¼
æ¢ç¶æå¤ç§ mode ï¼é£ä¹é½æåªäºå¢ï¼
æºç ä¸æå¦ä¸å®ä¹ï¼
å®ä»¬å¯¹åº Foundation ä¸çï¼
æ们é½æ¸ æ¥å¨é¡µé¢æ»å¨çæ¶åæä¸ä¸ª UITrackingRunLoopMode ï¼
é¤äºä»¥ä¸ 3 ç§ mode è¿æ两个ç§æ mode ï¼
å½ RunLoop è¿è¡å¨ Mode1 ä¸æ¶ï¼æ¯æ æ³æ¥åå¤ç Mode2 æ Mode3 ä¸ç SourceãTimerãObserver äºä»¶çã
以 timer 为ä¾ï¼å° timer å å ¥å° runloop ä¸ï¼
åºå±è°ç¨äº CFRunLoopAddTimer ï¼
æ ¹æ®è¦å å ¥ç mode åºåæ¯ common mode åé common mode å° timer å å ¥ mode ä¸ãè¿ä¸ªæ¶ååªæ¯å° timer å å ¥äº mode ä¸ï¼è¦æ§è¡è¯å®è¦è°ç¨ CFRunLoopRun ï¼æç»è¦è°ç¨ CFRunLoopRunSpecific ã
å¨ __CFRunLoopRun ä¸è°ç¨äº __CFRunLoopDoTimers ï¼
æ¾å° mode ä¸çææ timer ç¶åè°ç¨ __CFRunLoopDoTimer ã
CFRunLoopAddTimer -> CFRunLoopRunSpecific -> __CFRunLoopRun -> __CFRunLoopDoTimers -> __CFRunLoopDoTimer -> __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ ã
ä¸ timer ç¸å source ä¼è°ç¨ CFRunLoopAddSource ï¼
CFRunLoopAddSource -> CFRunLoopRunSpecific -> __CFRunLoopRun -> __CFRunLoopDoSources0/__CFRunLoopDoSources1 -> __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ /__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__
åç observer ä¼è°ç¨ CFRunLoopAddObserver ã
Backtrader来啦:可视化篇(重构)
量化投资与机器学习公众号为全网读者带来的Backtrader系列,深受欢迎,我们致力于提供免费、最清晰的Bt教程。QIML官方Github已上线,相关数据、vc 应用源码包代码一并同步,欢迎大家关注和星标。公众号希望为国内量化投资圈贡献一份力量,影响更多人了解和学习量化投资,找到适合自己的道路。如需分享内容,欢迎在评论区留言。oozie 源码 分析
今天的《可视化篇》将介绍Backtrader观测器模块observers与自带的绘图函数plot()。我们将通过修改图形样式,基于回测返回的收益序列TimeReturn,结合pyfolio和matplotlib工具,自定义可视化图形。获取完整代码+数据,见文末链接。
observers模块用于统计回测信息,并在plot()的帮助下实现可视化展示。最常用的观测器包括:
- Broker观测器:记录经纪商中各时间点的可用资金和总资产。可视化时,会同时展示cash和values曲线,健步走源码若需单独展示,可分别使用Cash和Value观测器。
- BuySell观测器:记录回测过程中的买入和卖出信号。可视化时,会在价格曲线上标注买卖点。
- Trades观测器:记录回测过程中每次交易的盈亏。可视化时,会绘制盈亏点。
- TimeReturn观测器:记录回测过程中的收益序列。可视化时,会绘制收益曲线。
- DrawDown观测器:记录回测过程的遇见系统源码回撤序列。可视化时,绘制回撤曲线。
- Benchmark观测器:记录业绩基准的收益序列,必须事先通过数据添加函数添加至大脑cerebro中。可视化时,同时绘制策略本身的收益序列和业绩基准的收益曲线。
如何添加观测器?observers通过addobserver()添加给大脑cerebro,参数obscls对应观测器类,args和kwargs对应观测器支持的设置参数。
如何读取观测器数据?观测器属于lines对象,可以通过self.stats对象在Strategy中读取数据。观测器的答题平台源码数据在所有指标计算完后、执行Strategy的next方法后运行并统计数据,因此读取的最新数据[0]相对与next的当前时刻晚一天。
如何自定义观测器?自定义观测器遵循继承bt.observer.Observer类,指定要统计的数据为相应的line,随着回测进行依次存入数据。作为Lines对象的Observers和Indicator类,内部都有plotinfo和plotlines属性,用于回测结束后通过cerebro.plot()方法进行可视化展示。
plot()图形绘制支持回测的三大内容:Data Feeds、Indicators和Observers。Data Feeds在回测开始前导入大脑,Indicators有的与Data Feeds一起绘制在主图上,有的以子图形式绘制,Observers通常绘制在子图上。
plot()中的参数用于系统性配置图形,如修改图形样式、主题颜色等。若需系统性修改图形样式,可以重新定义PlotScheme类,或直接在plot()中修改参数。关于主题颜色,Backtrader提供多种主题色,可通过复制源码中定义的颜色并结合tab_index进行修改。
局部绘图参数设置通过类内部的plotinfo和plotlines属性控制,plotinfo主要对图形整体布局进行设置,plotlines主要对具体line的样式进行设置。
基于收益序列进行可视化,Backtrader自带的绘图工具方便实用。此外,结合pyfolio和matplotlib,根据回测返回的分析器TimeReturn、pyfolio、matplotlib可以得到可视化图形。不同主题下绘制效果也有所不同。
关于回测结果的可视化,需求不同对应不同的可视化内容。Backtrader回测框架提供了友好的绘图接口,对于额外数据,可结合Backtrader分析器Analyzers返回的指标,选用Python绘图工具如Matplotlib、Seaborn、Plotly等进行可视化展示。
量化投资与机器学习微信公众号专注于量化投资、对冲基金、Fintech、人工智能、大数据等领域,是业内主流自媒体,拥有来自公募、私募、券商、期货、银行、保险、高校等行业W+关注者,曾荣获AMMA优秀品牌力、优秀洞察力大奖,连续4年被腾讯云+社区评选为“年度最佳作者”。公众号致力于提供专业、全面的内容,帮助读者深入学习量化投资知识和技能。
LiveDataBus
LiveDataBusæ¯åºäºLiveDataå®ç°ç类似EventBusçæ¶æ¯éä¿¡æ¡æ¶ï¼å®æ¯åºäºLiveDataå®ç°çï¼å®å ¨å¯ä»¥ä»£æ¿EventBusï¼RxBusï¼LiveDataBusç主è¦æ¯åºäºåå¸è®¢é 设计模å¼ï¼åå¸è®¢é 模å¼å®ä¹äºä¸ç§ âä¸å¯¹å¤â çå ³ç³»ï¼åè§å¯è 模å¼æ¯å®å ¨ä¸åç两个设计模å¼ï¼
ä¸é¢è¯¦ç»ä»ç»æ ¸å¿ç±»LiveData
LiveDataæ¯ä¸ä¸ªå¯ä»¥è¢«è§å¯çæ°æ®holderï¼å¹¶ä¸å¯ä»¥èªå¨æç¥æ§ä»¶ççå½å¨æï¼ä¸ä¼åçå åæ³æ¼ï¼
LiveDataéè¦ä¸ä¸ªè§å¯è 对象ï¼å½LiveDataçå¼åçæ¹åæ¶ï¼è§å¯è ä¼å¯è§å°è¿ä¸ªæ¹åï¼
使ç¨livedata注åè§å¯è çå¬
使ç¨livedataåéæ¶æ¯ç»è§å¯è
LiveDataå ¶å®å°±æ¯ä¸ä¸ªåæ¾æ°æ®çholderï¼ç±»ä¼¼ViewHolderçholderï¼åæ¾å¨LiveDataéçæ°æ®ä¼æ¥æLiveDataçç¹æ§ï¼
LiveDataæ¯Android Architecture Componentsçä¸ä¸ªç±»ï¼è¿ä¸ªç±»æ¯è°·æå¨Google I/O åå¸ä¸å¥å¸®å©å¼åè 解å³Androidæ¶æ设计çæ¹æ¡ãè¿ä¸ªç±»æåä¸ªæ ¸å¿ï¼åç»ä¼ä¸ä¸ä»ç»ï¼
ç¨ç¬¬ä¸ä»£LiveDataBus订é
åéæ¶æ¯
è³äºè¯´ä»æ¯ç¬¬ä¸ä»£busï¼è¯´æè¯å®æé®é¢ï¼é®é¢å°±æ¯å¨postæè setä¸ä¸ªvalueåï¼åªè¦å¨ä¸ä¸ªfrag/actéobserveäºï¼æ 论ç»ä»¶æ¯å¦å¯å¨ï¼é½ä¼æ¶å°valueï¼å³å½å¨act1ä¸postäºï¼å¨act2ä¸observeï¼ä½æ¯postçæ¶åact2没æè¿è¡ï¼å½å¯å¨act2ï¼æ¶å°äºvalueãæ¶å°äºè®¢é åçæ¶æ¯
éè¿æ¥çLiveDataçæºç åç°setValueï¼ï¼å¼å§ï¼ä¾æ¬¡è°ç¨äº
dispatchValue()-> considerNotify()-> observer.onChanged()
postValue()ä¼è°ç¨setValueï¼ï¼æ以åçï¼
è¿å°±è§£éäºä¸ºä»ä¹æ们å¯ä»¥å¨observerä¸æ¶å°postæ¥çvalueï¼ä¸ºä»ä¹act2ä¸è¿è¡ä¹å¯ä»¥æ¶å°valueï¼
æ们注æå°å½observer.mLastVersion >= mVersionçæ¶åä¼ç´æ¥returnï¼ä¸è°ç¨onChangedä»è解å³ä¸é¢çé®é¢ã
æ们éè¦æ¿å°mLastVersionï¼å°±éè¦æ¿å°observer对象ï¼é¡ºçæºç åç°observer对象åå¨mObserversçmapä¸ï¼æ们èªå®ä¹ä¸ä¸ªmutableLiveDataï¼æ¹åä»çobserveï¼ï¼ï¼å¨observeï¼ï¼ä¸ï¼éè¿åå°æ¿å°mObservers对象ï¼ä»èæ¿å°observer.mLastVersionï¼å°mVersionèµå¼ç»ä»ï¼
hookçä½ç¨ç¸å½äº å¨observeï¼ï¼è°ç¨åæ§è¡observer.mLastVersion = mVersion; 让considerNotifyï¼ï¼ç´æ¥returnï¼å¯æ¯æ们å¦ä½æ¶å°è®¢é åçpostå¢ï¼å 为åªæ订é çæ¶åæä¼hookï¼å¨hookåï¼æ们è°ç¨postï¼ï¼ï¼ä¼mVersion++ï¼æ以å¨å¤æ if (observer.mLastVersion >= mVersion) çæ¶åå°±åä¼æ¯falseäºï¼