: | : | :期货量化学习 | :期货量化 |
返回列表 发帖

OpenD、HighD、LowD和CloseD系列函数

OpenD、HighD、LowD和CloseD系列函数

一、简介1. 系列函数功能介绍

        OpenD、HighD、LowD和CloseD系列函数都是通过调用OHLCPeriodsAgo或者OHLCPeriodsAgoGen函数来返回指定时间段内的指定价格,例如HighD(0)返回当天的最高价,HighD(1)返回前一天的最高价,以此类推,但是最多只能返回当天之前的第50天的最高价,也就是说HighD(51)不允许使用,HighD(50)允许使用,最多向历史引用50个数据对该系列所有函数都适用;由于OHLCPeriodsAgo和OHLCPeriodsAgoGen两个函数都返回开高低收4个价格,所以它们的参数需要用到numericref传址类型来输出多个结果。

         由于指定时间段内的开、高、低和收盘价格的计算原理是相同的,所以我这里只对最高价的相关内容进行阐述,开盘价、最低价和收盘价格可以根据最高价的内容进行类推,在此不再赘述;HighS、HighD、HighW、HighM、HighY函数都是返回指定时间段的收盘价,不同的是,它们返回的是不同的时间周期的收盘价,五个函数后面的大写字母分别是S、D、W、M和Y,五个字母分别代表Session(时段)、Day(日)、Week(周)、Month(月)、Year(年),由于HighD和HighW、HighM、HighY函数的原理相同,所以这里我着重阐述HighS和HighD的相关内容,HighW、HighM、HighY函数的相关内容可以根据HighD进行类推;OpenD、HighD、LowD和CloseD系列函数的功能的简单介绍可以看表1 OpenD、HighD、LowD和CloseD系列函数。

          关于日期的定义,表1中出现两个名词,一个是交易所时段,另一个是物理时段。交易所时段的一天,指的是将前一天晚上的夜盘计算到当天的日盘上,HighS返回指定日(比如2017-08-03号)的最高价,那么实际返回的就是指定日前一天夜盘(2017-08-02号晚上)和指定日(2017-08-03号)白天的商品合约的最高价格,这是对于内盘期货而言是这样计算的;对于股票,由于没有夜盘,所以HighS只计算日盘的最高价格;对于外盘期货,HighS的计算也是按照交易所时段来计算的,这个具体看外盘交易所如何规定交易日的时间范围。物理时段的一天,很好理解,就是从指定日的00:00:00到23:59:59的时间范围内的最高价格;物理时段的一周、一月和一年都是基于物理时段的一天进行累加,所以HighW返回的是指定周的最高价,HighM返回的是指定月的最高价,HighY返回的是指定年的最高价。

2. 内容安排

        本文分成五个大部分,由浅由深的阐述OpenD、HighD、LowD和CloseD系列函数的功能介绍、计算原理、灵活运用、代码解析及函数扩展与构造;如果您只是想基本了解该系列函数的基本用法,您只需要看第一部分;如果您想在使用中避免一些误区,那么您需要看前三个部分;如果您想理解该系列函数的代码逻辑以便于完全掌握它们,甚至通过学习该系列函数的构造原理,您需要构造相同逻辑的其它功能函数,那么您需要看完这篇文章。

表1 OpenD、HighD、LowD和CloseD系列函数

  

MC函数名称

函数功能

OHLCPeriodsAgo

通过传址参数,输出指定时间段内的开、高、低和收盘价格

OpenS

调用OHLCPeriodsAgo函数,返回指定日(交易所时段)的开盘价

OpenD

调用OHLCPeriodsAgo函数,返回指定日(物理时段)的开盘价

OpenW

调用OHLCPeriodsAgo函数,返回指定周(物理时段)的开盘价

OpenM

调用OHLCPeriodsAgo函数,返回指定月(物理时段)的开盘价

OpenY

调用OHLCPeriodsAgo函数,返回指定年(物理时段)的开盘价

HighS

调用OHLCPeriodsAgo函数,返回指定日(交易所时段)的最高价

HighD

调用OHLCPeriodsAgo函数,返回指定日(物理时段)的最高价

HighW

调用OHLCPeriodsAgo函数,返回指定周(物理时段)的最高价

HighM

调用OHLCPeriodsAgo函数,返回指定月(物理时段)的最高价

HighY

调用OHLCPeriodsAgo函数,返回指定年(物理时段)的最高价

LowS

调用OHLCPeriodsAgo函数,返回指定日(交易所时段)的最低价

LowD

调用OHLCPeriodsAgo函数,返回指定日(物理时段)的最低价

LowW

调用OHLCPeriodsAgo函数,返回指定周(物理时段)的最低价

LowM

调用OHLCPeriodsAgo函数,返回指定月(物理时段)的最低价

LowY

调用OHLCPeriodsAgo函数,返回指定年(物理时段)的最低价

CloseS

调用OHLCPeriodsAgo函数,返回指定日(交易所时段)的收盘价

CloseD

调用OHLCPeriodsAgo函数,返回指定日(物理时段)的收盘价

CloseW

调用OHLCPeriodsAgo函数,返回指定周(物理时段)的收盘价

CloseM

调用OHLCPeriodsAgo函数,返回指定月(物理时段)的收盘价

CloseY

调用OHLCPeriodsAgo函数,返回指定年(物理时段)的收盘价

OHLCPeriodsAgoGen

相比OHLCPeriodsAgo函数,该函数只是多了一个参数(子图编号)

HighDGen

调用OHLCPeriodsAgoGen函数,返回子图指定日(物理时段)的最高价

LowDGen

调用OHLCPeriodsAgoGen函数,返回子图指定日(物理时段)的最低价

二、计算原理

        HighS和HighD的计算原理实际上是通过逐个比较图表上指定日内的bar的最高价,来确定指定日的最高价(例如,图表的周期为1分钟,那么通过逐个比较前一天的每一根bar的最高价,最后将前一天所有的bar的最高价中的最大值通过HighD(1)返回),所以图表的周期不能大于1日;若图表的周期是2日,那么通过HighD和HighS返回的其实是指定bar的最高价,例如HighD返回的是当根bar的最高价,HighD(1)返回的是前一根bar的最高价,以此类推,因为HighD是的通过条件语句date<>date[1]进行判断的(就是当根bar的日期和前一根bar的日期进行比较,来区分不同的日),有点不一样的是,HighS是通过条件语句sessionlastbar[1]进行判断的;若图表的周期是1周及以上,那么HighD和HighS返回的是-1(还有两种情况是返回-1的,那就是当引用的数据超过50,例如HighD(51)返回-1,或者当数据不够时,也会返回-1,因为默认值是-1),这个判断是通过条件语句condition1=PeriodsAgo > 50 or BarType >2 or BarType > 4 进行判断的(bartype关键字是判断图表的周期类型,详细的可以看一下这个关键字的解释),当这个条件语句condition1成立的时候,返回值为-1。

        所以在使用函数HighS和HighD时,图表的周期设为日内(秒、分、时)、ticks、合约或者1日;在使用函数HighW时,图表的周期需要设为日内(秒、分、时)、ticks、合约、1日或者1周(这里不建议使用周期是3日,因为这样会使某根bar上的数据分别来自两周,而函数HighW的计算中会根据bar的收盘时间来区分不同的周,所以最终会导致HighD返回错误的最高价,类似的情况在使用其它函数的时候也会出现);在使用函数HighM时,图表的周期需要设为日内(秒、分、时)、ticks、合约、1日、1周或者1月;在使用函数HighY时,图表的周期需要设为日内(秒、分、时)、ticks、合约、1日、1周、1月、2月、3月、4月、6月或者1年。

三、灵活运用1. 关键字sessionlastbar

        前面已经阐述了交易所时段是根据关键字sessionlastbar来识别的,那么sessionlastbar是如何判断交易时段结束,这个可以在MC的报价管理器中交易时段设置中看到;现在举例上海期货交易所商品合约shfe.rb hot的交易时段(对应报价管理器交易时段),如表2 shfe.rb hot交易时段所示。

       Sessionlastbar识别的是“结束”,两个“结束”之间的时间范围是一个“交易所时段”,而这个和实际的交易所时段是有一定的差别的;实际的交易日时段会将周五夜盘的行情计算到下周一的白天行情中,而sessionlastbar会将星期五的夜盘行情单独计算为一个交易日时段,星期一白天的行情单独计算为一个交易日时段。由于HighS是利用sessionlastbar关键字对交易日时段进行区分的,所以HighS并不能完全取到每一个实际交易日时段的最高价。

表2 shfe.rbhot交易时段

开盘

时间

收盘

时间

时段结束

星期一

09:00

星期一

13:30

星期一

13:30

星期一

15:00

结束

星期一

21:00

星期一

23:00

星期二

09:00

星期二

13:30

星期二

13:30

星期二

15:00

结束

星期二

21:00

星期二

23:00

星期三

09:00

星期三

13:30

星期三

13:30

星期三

15:00

结束

星期三

21:00

星期三

23:00

星期四

09:00

星期四

13:30

星期四

13:30

星期四

15:00

结束

星期四

21:00

星期四

23:00

星期五

09:00

星期五

13:30

星期五

13:30

星期五

15:00

结束

星期五

21:00

星期五

23:00

结束

2. 子图运行机制

        在图表上(为方便起见,这里将最大bar设置为0,不开启bar内)可以插入一个子图(多个子图是同样的道理),主图上的bar和子图的bar在图表上是以收盘时间进行先后排列的,如果主图上的bar(为方便叙述记为A)和子图上的bar(为方便叙述记为B)的收盘时间相同,那么这两个bar会在图表上同一条垂直线上排列;如果A的收盘时间小于B,那么A在B的左边排列,B在A的右边排列。如果在代码中不出现data2,那么实际上主图上有多少根bar,代码就计算多少次,也就是说代码执行地计算不考虑子图data2的存在;如果代码中出现data2,那么实际上代码的计算会考虑图表上所有的bar的数目,每一根bar收盘都会计算一次,在同一垂直线上bar(分别来自不同的子图和主图)只会计算一次。

       这个部分会很难理解,因为还涉及“重新计算“和”更新“的概念,需要大家多多测试代码(利用print输出数据进行观察),详细的解释参考图1和图2进行进一步学习

3. OHLCPeriodsAgoGen 和HighDGen函数

        OHLCPeriodsAgoGen和OHLCPeriodsAgo的区别在于使用了子图的数据,而HighDGen函数是调用OHLCPeriodsAgoGen函数,返回子图指定日(物理时段)的最高价。尽管HighDGen函数是代码计算中逐个比较子图中每一根bar的最高价然后取最高价返回,但是这其中会涉及两种计算,一种是“重新计算”,另一种是“更新”,只有当代码的计算是基于主图的bar进行计算(也就是“更新”),此时的比较才是有意义的,这时候比较出来的最高价才会通过HighDGen函数返回。例如,主图是1小时周期,子图是1分钟周期,假设2017-08-02号有7根小时bar,那么只是在7次基于主图bar计算时取的子图的7个最高价进行比较,然后通过HighDGen函数返回7个中的最高值。这部分内容,有兴趣可以自己研究一下。

四、代码简析

        这部分以OHLCPeriodsAgo函数内部代码进行解析,该系列其它函数根据这个函数的解析就很好理解了。HighS、HighD、HighW、HighM和HighY函数都是调用OHLCPeriodsAgo函数返回相应时段的最高价,而OHLCPeriodsAgo函数内部是通过参数PeriodType对这5个函数进行区分计算(PeriodType为0时,表示Session;PeriodType为1时,表示Day;PeriodTypeo为2时,表示Week;PeriodType为3时,表示Month;PeriodType为4时,表示Year)另外一个重要的参数是PeriodsAgo,这个是向历史引用的参数,最多只能向历史引用50个数据。代码的解析以HighD为例。

inputs:

       PeriodType( numericsimple ),                                               

       PeriodsAgo( numericsimple ),

       oPeriodOpen( numericref ),

       oPeriodHigh( numericref ),

       oPeriodLow( numericref ),

       oPeriodClose( numericref ) ;

{oPeriodOpen、oPeriodHigh 、oPeriodLow和oPeriodClose都是传址参数,它们分别用于输出开盘价、最高价、最低价和收盘价}

variables:

       var0( 0 ), sess_last_bar(false) ;

arrays:

       arr0[ 4, 50 ]( -1 ) ;

{OHLCPeriodsAgo函数在PeriodType和PeriodsAgo这个参数确定的情况下会返回4个价格(开盘价、最高价、最低价和收盘价),而数组arr0被用于存储这4个价格,每个价格会有50个历史数据被存储在这个数组中,方便调用,默认初始值为-1;因为多维数据不能动态调用数组大小,所以最多只能向历史引用50个数据}

sess_last_bar = sessionlastbar;

condition1 = PeriodsAgo > 50 or BarType > IFF(PeriodType<>0, PeriodType + 1, PeriodType + 2) or BarType > 4 ;

{这部分是判断语句,当condition1成立时,所有都返回-1;也就是说,它限制向历史引用的数据超过50,它只允许图表的周期类型是ticks、合约、秒、分、时、日、周、月、季和年,它不允许图表的周期大于需要返回的交易时段(这里的逻辑并不很严谨)}

if condition1 then

       begin

       oPeriodOpen = -1 ;

       oPeriodHigh = -1 ;

       oPeriodLow = -1 ;

       oPeriodClose = -1 ;

       OHLCPeriodsAgo = -1 ;

       end

else

       begin                                       

       if PeriodType = 0 then

              Condition1 = sess_last_bar[1]

       else if PeriodType = 1 then

              Condition1 = Date <> Date[1]

       else if PeriodType = 2 then

              Condition1 = DayOfWeek( Date ) < DayOfWeek( Date[1] )

       else if PeriodType = 3 then

              Condition1 = Month( Date ) <> Month( Date[1] )

       else if PeriodType = 4 then

              Condition1 = Year( Date ) <> Year( Date[1] ) ;

{通过PeriodType来判断session、Day、Week、Month和Year}

       condition1 = CurrentBar = 1 or Condition1 ;

{当currentbar=1成立时或者当根bar的日期和前一根bar的日期不一致时,那么首先将当根bar的最高价赋值给arr0[2,var0],因为是新的交易日的开始,所以必须存储到数组的新的存储单元中,那么这个是通过var0循环减一达到目的的}

if condition1 then                                         

              begin

              var0 = var0 - 1 ;

              if var0 = -1

                     then var0 = 50 ;                                                           

              arr0[ 1, var0 ] = O ;

              arr0[ 2, var0 ] = H ;

              arr0[ 3, var0 ] = L ;

              arr0[ 4, var0 ] = C ;

              end

       else                                 

              begin

              condition1 = H > arr0[ 2, var0 ] ;

              if condition1 then arr0[ 2, var0 ] = H ;

              condition1 = L < arr0[ 3, var0 ] ;

              if condition1 then arr0[ 3, var0 ] = L ;

              arr0[ 4, var0 ] = C ;

              end ;

{当Date=Date[1]时,执行else语句,也就是逐个将当前bar的最高价与arr0[2,var0]进行比较,然后将最大的值重新存储在arr0[2,var0]中,不断更新}

       oPeriodOpen = arr0[ 1, Mod( var0 + PeriodsAgo, 51 ) ] ;

       oPeriodHigh = arr0[ 2, Mod( var0 + PeriodsAgo, 51 ) ] ;

       oPeriodLow = arr0[ 3, Mod( var0 + PeriodsAgo, 51 ) ] ;

       oPeriodClose = arr0[ 4, Mod( var0 + PeriodsAgo, 51 ) ] ;

{执行完if-else语句之后,再更新oPeriodHigh;这里使用到数学中的求余的技巧,举例一下就比较清楚了;当PeriodsAgo为0时,那么oPeriodHigh的值是不断更新变化的,当然HighD(PeriodsAgo)也是不断更新变化的;当PeriodsAgo为1时,那么oPeriodHigh的值取的是arr0[2,var0+1]的值,这个值不会每根bar都变化了,它是前一日的最高价}

       OHLCPeriodsAgo = 1 ;

       end ;            

if false then

    Value1 = OHLCPeriodsAgo[1] ;

五、函数扩展与构造

这个是计算指定日(物理时段)的成交量的函数代码,由于使用的是动态数组,所以它向历史引用的数据不受数量的限制;这个代码在附件中,有兴趣的可以下载一下。


论坛官方微信、群(期货热点、量化探讨、开户与绑定实盘)
 
期货论坛 - 版权/免责声明   1.本站发布源码(包括函数、指标、策略等)均属开放源码,用意在于让使用者学习程序化语法撰写,使用者可以任意修改语法內容并调整参数。仅限用于个人学习使用,请勿转载、滥用,严禁私自连接实盘账户交易
  2.本站发布资讯(包括文章、视频、历史记录、教材、评论、资讯、交易方案等)均系转载自网络主流媒体,内容仅为作者当日个人观点,本网转载此文出于传递更多信息之目的,并不意味着赞同其观点或证实其描述。本网不对该类信息或数据做任何保证。不对您构成任何投资建议,不能依靠信息而取代自身独立判断,不对因使用本篇文章所诉信息或观点等导致的损失承担任何责任。
  3.本站发布资源(包括书籍、杂志、文档、软件等)均从互联网搜索而来,仅供个人免费交流学习,不可用作商业用途,本站不对显示的内容承担任何责任。请在下载后24小时内删除。如果喜欢,请购买正版,谢谢合作!
  4.龙听期货论坛原创文章属本网版权作品,转载须注明来源“龙听期货论坛”,违者本网将保留追究其相关法律责任的权力。本论坛除发布原创文章外,亦致力于优秀财经文章的交流分享,部分文章推送时若未能及时与原作者取得联系并涉及版权问题时,请及时联系删除。联系方式:http://www.qhlt.cn/thread-262-1-1.html
如何访问权限为100/255贴子:/thread-37840-1-1.html;注册后仍无法回复:/thread-23-1-1.html;微信/QQ群:/thread-262-1-1.html;网盘链接失效解决办法:/thread-93307-1-1.html

图1 主图和子图2


图2 重新计算和更新
如何访问权限为100/255贴子:/thread-37840-1-1.html;注册后仍无法回复:/thread-23-1-1.html;微信/QQ群:/thread-262-1-1.html;网盘链接失效解决办法:/thread-93307-1-1.html

TOP

返回列表