资源加载中... loading...

My语言商品期货量化交易教程:在优宽平台开始你的My语言量化之旅

Author: ianzeng123, Created: 2024-01-02 09:10:54, Updated: 2024-06-13 14:51:08

ACD就可以获取到。

FASTLINE^^EMA(CLOSE,12);
SLOWLINE^^EMA(CLOSE,26);
DIF:FASTLINE-SLOWLINE,CIRCLEDOT;
DEA:EMA(DIF,9);
MACDDIFF:2*(DIF-DEA),COLORSTICK, IF(2*(DIF-DEA), COLORRED, COLORGREEN);

为了在图形中更好的呈现,我们将快线和慢线使用两个上箭头画在主图上,DIF,DEA,和MACDDIFF使用冒号在副图上进行呈现。另外,这里面可以给大家补充一下画图的函数,在优宽平台,支持的My语言画图函数有这些:

函数 意义
CIRCLEDOT 小圆点线
COLORSTICK 画柱线(水平线为0)
DOT 画虚线
VOLUMESTICK 画柱线(水平线为最小值)
COLORRED 红色

所以这里将DIF线使用小圆点线,MACDDIFF使用COLORSTICK以0为水平轴的柱线,然后使用不同的颜色进行线的呈现。这里比较特别的一点是,我们可以使用IF语句设置不同颜色的MACD柱,当MACD值为正的时候,设置为红色;否则设置为绿色,这样经典的MACD指标就使用My语言进行了复现。

我们继续金融统计函数的讲解,这里还具有一些函数可以帮助我们判断条件和周期的关系,比如BARSCOUNT,返回第一个有效周期到当前的周期数;BARSLAST,上一次条件COND成立到当前的周期数;BARSSINCE,第一个条件成立到当前的周期数;BARSSINCEN,统计N周期内第一次条件成立到当前的周期数;CONDBARS,取得最近的满足A、B条件的k线间周期数;COUNT,统计N周期中满足COND条件的周期数。使用这些函数,我们可以结合具体的条件,进行具体指标的设置。

我们可以举一个例子,如果要统计最近20天内大涨的天数,我们应该编写呢?大涨我们可以设定一个范围,如果实时的收盘价大于昨日的收盘价2%的时候,我们就定义为大涨。将这个条件设置好以后,我们使用COUNT统计一下20天内满足这个条件的天数。具体的代码可以这样编写:

DAZHANG: =CLOSE/REF(CLOSE,1) >1.02;
INFO(1, COUNT(DAZHANG, 20), '大涨天数');

K线周期设置为天,品种这里我们选择纸浆,可以看到返回结果是1,证明在这20天内有1天涨幅是大于2%的。

辛苦大家听完这节课,介绍了这么多的函数。在我们前期课程了解数据返回机制的基础上,理解各个函数的数据获取和计算机制应该是比较清晰的。这些函数是我们进行金融指标计算和交易信号判断重要的组成部分,下节课在指标计算基础上,我们将要最后一部分,交易函数的使用。我们下节课再见。

六、交易函数(一)

前面的课程我们介绍了实时数据获取,条件逻辑判断,指标计算的函数,都是为了指标的计算和交易信号的判断,在获取交易信号以后,接下来我们就要来进行交易中最重要的一环,具体交易操作的执行。

交易指令

在My语言中,交易操作是通过交易函数来实现的。My语言具体的交易操作有下面七个指令。

B: BUY; S: SELL; K: 开; P:开

BK:基本下单指令,买入开仓,建立多头持仓

SP:基本下单指令,卖出平仓,平掉多头持仓

SPK:反手下单指令,卖平后卖开,多单转空单

SK:基本下单指令,卖出开仓,建立空头持仓

BP:基本下单指令,买入平仓,平掉空头持仓

BPK:反手下单指令,买平后买开,空单转多单

CLOSEOUT: 清仓指令

怎样记忆呢,其实My语言很有意思,它有点中西结合的味道。比如这里的B是英文Buy的简写,S是Sell的简写,K是中文“开”的简写,P是“平”的简写。所以进行组合买开BK是开多仓。平多仓我们需要将这两个字母取相反,B的相反是S,K的相反是P,所以是SP,卖出平仓。而SPK是先进行平多仓,再进行相反方向开仓,也就是开空,所以SPK是多转空。这就是多仓设置的逻辑。

对于空仓设置的逻辑我们也可以理解了,SK是卖出开仓,建立空头,取相反BP是平空,进而BPK是平空开多。

还有最后一个设置CLOSEOUT,是清仓,平掉所有方向的持仓。

这里的交易指令是可以添加参数的,代表具体下单的手数。例如“BK(2)”代表开了两手多仓。如果没有参数,就是用交易类库中的默认下单手数进行下单。

在My语言的交易函数中,有些地方需要注意。第一,My语言是不支持限价单的,也就是不能限制具体交易的价格;当我们需要限制下单价格的时候,我们可以写成条件的形式,如果满足价格限制的条件,再执行具体交易的操作,但是也有可能市场波动的因素,不能严格的执行。

第二,对于平仓这里,是没有“平今”和“平昨”区别的。我们直接使用就可以。

我们举例示范一下。我们建立一个简单的交易的模型。这里的开仓条件是如果不在距离收盘10分钟以内,并且收盘价大于开盘价,就进行开多仓;相反情况下,进行开空仓;如果时间到达收盘价10分钟内,我们就要平掉持有的多仓或者空仓。所以这里使用还可以写作CLOSEOUT平掉所有仓位。这里的AUTOFILTER是一开一平的模式,也就是一个方向开仓以后,不能继续加仓,只有平仓以后,才能继续开仓,这涉及到My语言的交易逻辑,我们稍后进行讲解。

C>O && TIME<1450,BK;
C<O && TIME<1450,SK;
TIME >= 1450,SP;
TIME >= 1450,BP;
// TIME>=1450,CLOSEOUT;
AUTOFILTER;

因为My语言只能支持单向的持仓,所以在策略当中,也可以使用BPK,先平空仓再开多仓,和SPK先平多仓再开空仓,进行交易操作的执行。这里我们举一个简单的双均线策略。首先我们设置两条均线MA5,和MA10,当MA5上穿MA10的时候,我们进行平空开多;当MA5下穿MA10,进行平多开空。这里大家可能会有疑问,如果策略开始的时候,没有持有仓位,怎么进行平仓,其实这时候就是只进行开仓了,不进行平仓。

MA5^^MA(CLOSE, 5);
MA10^^MA(CLOSE,10);
CROSSUP(MA5, MA10), BPK;
CROSSDOWN(MA5, MA10), SPK;
AUTOFILTER;

交易控制函数

下面我们讲一下交易信号和具体交易操作执行逻辑的设置。交易操作是伴随交易信号的确定去执行的。对于不同的交易类型,我们需要对信号进行信号过滤或者重复执行的操作。我们可以通过交易控制函数设置交易信号和交易操作执行的逻辑。

AUTOFILTER

模型中通过写入AUTOFILTER函数来控制和实现一开一平的信号过滤,有多个开仓信号都满足条件的时候,取第一个信号作为有效信号,后面的k线上的同样信号将被过滤掉。

这里我们设置一个策略。首先计算两条均线,MA5和MA10,然后这里判断两个开仓条件,第一个条件是如果收盘价大于MA5,第二个是MA5大于MA10;在分别满足其中一个条件的情况下,使用INFO进行日志的输出,并使用BK进行多头的开仓;平仓条件是如果收盘价大于BKPRICEAV,这是多头持仓的平均价加上5,我们进行止盈;或者收盘价小于BKPRICEAV-5,进行止损,使用SP平掉所有的多头持仓数量,这个内置变量是BKVOL。

MA5:MA(CLOSE,5);
MA10:MA(CLOSE,10);
SIG1 := CROSSUP(C,MA5);
SIG2 := CROSSUP(MA5,MA10);
INFO(SIG1,'开仓条件1满足#FF0000');
INFO(SIG2,'开仓条件2满足#00FF00');
SIG1,BK;
SIG2,BK;
C>BKPRICEAV+10||C<BKPRICEAV-5,SP(BKVOL);
//AUTOFILTER;

如果设置AUTOFILTER,触发BK后,只能触发SP,其它的BK信号被忽略,每根K线触发一次信号。回测这里我们设置k线周期为分钟,收盘价模型,结果这里看到,在相应条件满足情况下,每根k线产生一个信号,开仓只能进行1手,即使开仓条件2满足,或者开仓条件重复满足,也选择忽略。开仓过后,下一次的交易操作必然是平仓。平仓过后才可以进行下一次的开仓。在平仓过后,重置了模型状态。

这个就是AUTOFILTER,我们在策略当中使用的最多的模型,一开一平的模式。

我们可以对比尝试一下,不设置AUTOFILTER时。我们来看下回测结果。同样可以看到在具体条件满足的情况下,每根k线产生一个信号;这里不再限于必须是开仓平仓的模型,当两个条件都满足,就会进行两次的开仓操作;但是每条指令都只能执行一次,在某一指令开仓完成后,即使重复满足,也会选择忽略。但是有时候我们想要进行加仓的操作,需要重复执行某条指令,这时候我们就要使用下一种模式,TRADE_AGAIN。

TRADE_AGAIN

刚才上面的举例中,我们看到即使没有设置AUTOFILTER,但是每行交易指令在执行过后,是不能重复执行的,只有在平仓过后,重置模型状态,才可以重新执行相应的指令。怎样可以重复执行同一个命令行呢,我们可以设置 TRADE_AGAIN函数,它是具有参数的,具体的参数代表代表指令行可以进行几次的操作。

MA5:MA(CLOSE,5);
INFO(CROSSUP(C,MA5),'开仓条件1满足#FF0000');
CROSSUP(C,MA5),BK;
C>BKPRICEAV+5||C<BKPRICEAV-5,SP(BKVOL);
TRADE_AGAIN(2);

这里我们设置满足条件1的情况下,我们进行开多仓;首先不设置TRADE_AGAIN函数,可以看到即使多次满足条件1,然而具体操作的执行只有1次;我们加上TRADE_AGAIN函数,参数设置为2,可以看到该行指令被执行了两次,第三次以后被选择忽视。这就是TRADE_AGAIN函数的作用。

MULTSIG

以上呢,我们使用的都是收盘价模型,一根k线产生1个指令,就是只有在K线更新完毕我们才执行交易的操作,我们也可以选择实时价模型。这里我们更改为是实时价模型,并使用实盘级的tick,可以看到在一根k线上(67)即使满足了多个开仓条件,只有在下一根k线满足的时候,才进行继续加仓的操作,这就是一根K线一个信号的模型;如果对于高频级的tick策略,我们想要实现一根K线多个信号的模型,可以使用MULTSIG函数。

MULTSIG(Sec1,Sec2,N,INTERVAL)

这里首先给大家介绍一下MULTSIG各个参数的含义,这里最重要的参数是N,代表一根K线上最大的信号个数;Sec1和Sec2代表开仓和平仓出信号后不复核的时间,可以直接设置为0就可以;INTERVAL是数据时间间隔,也可以填写为空值。

以前我们讲过,1根k线是由很多tick数据组成的;相对于收盘价模型,一根k线产生一个信号,实时价模型里,一个tick就会产生一个信号,所以更加灵敏。使用MULTSIG模型就可以执行tick级别的策略。

这里我们编写一个策略示范一下。需要注意的是,因为这里是在一根k线上重复执行某个指令行,所以MULTSIG要配合TRADE_AGAIN函数。这里我们在先前函数基础上,添加MULTSIG(0,0,5),代表有信号出现,立刻执行,每个k线上最多可以执行5次指令,配合TRADE_AGAIN(5)函数,我们运行一下。根据日志,在满足开仓条件下,在同一根k线,我们进行了5次的开仓操作,同样的平仓也是。

MA1:MA(CLOSE,5);
MA2:MA(CLOSE,10);
CROSSUP(MA1,MA2),BK;
C>BKPRICE+10||C<BKPRICE-5,SP;
MULTSIG(0,0,5);
TRADE_AGAIN(5);

以上呢,就是我们在My语言中经常使用到的交易模式,大家可以根据自己策略的需要,选择合适的模式进行设置。另外,My语言还有一些内置函数和交易类库,都可以帮助我们进行交易的更多设置,我们下节课进行讲解。

七、交易函数(二)

上节课,我们讲到了My语言中基本的下单指令和交易模式。然而在下单完成以后,我们需要及时检查持仓的状态并进行相应的风险管理。因此,My语言还有一系列的交易状态检查函数,下面我们进行一下讲解。

信号函数

首先我们讲解一下对于多头开仓的信号记录函数。

  • BKVOL: 买开信号手数
  • BKPRICE: 返回数据合约最近一次买开信号价位
  • BKPRICEAV:返回数据合约多头开仓均价
  • BKHIGH:返回合约买开仓以来的最高价
  • BKLOW:返回数据合约买开仓以来的最低价

我们举例示范一下,这里我们设置开仓信号是收盘价大于5周期均线的时候,进行多头开仓,平仓信号是当收盘价大于开仓均价BKPRICEAV加上10,进行止盈,或者收盘价小于开仓均价减去10,进行止损,平仓的手数是所有的持仓数量,BKVOL。这里使用到了TRADE_AGAIN设置开仓指令可以执行3次。这里使用一系列的信号记录函数,具体的包括输出BKVOL,多头开仓手数;BKPRICE最近一次买开信号价位;BKPRICEAV,多头开仓均价;BKHIGH和BKLOW,返回开仓以来最高价和最低价。

MA1^^MA(CLOSE,5);
CROSSUP(C,MA1),BK;
INFO(1,BKVOL,'多头开仓手数#FF0000');
INFO(1,BKPRICE,'最近一次买开信号价位#00FF00');
INFO(1,BKPRICEAV,'多头开仓均价#0000FF');
INFO(1,BKHIGH,'开仓以来最高价#0000FF');
INFO(1,BKLOW,'开仓以来最低价#0000FF');
C>BKPRICEAV+10||C<BKPRICEAV-10,SP(BKVOL);
TRADE_AGAIN(3);

可以看到,策略运行开始,没有进行开仓的时候,这几个值返回0;然后伴随开仓和加仓,这几个函数伴随策略的进度,返回相应的数值。

对于空头开仓的信号记录函数,相信大家也可以理解具体的含义,这些函数可以帮助我们实时检查策略的运行状态。

  • SKVOL: 卖开信号手数
  • SKPRICE: 返回数据合约最近一次卖开信号价位
  • SKPRICEAV:返回数据合约空头开仓均价
  • SKHIGH:返回合约卖开仓以来的最高价
  • SKLOW:返回卖开仓以来的最低价

接下来一系列函数用来判断上一个信号是否是具体的哪些指令,返回值是布尔值的形式,1代表真,0代表假。

  • ISLASTBK:判断上一个信号是否是 BK
  • ISLASTSK:判断上一个信号是否是 SK
  • ISLASTBP:判断上一个信号是否是 BP
  • ISLASTSP:判断上一个信号是否是 SP
  • ISLASTBPK:判断上一个信号是否是 BPK
  • ISLASTSPK:判断上一个信号是否是 SPK
  • ISLASTCLOSEOUT:判断上一个信号是否是 CLOSEOUT

还有一系列函数用来判断具体的信号距离当前k线的根数。

  • BARSBK:上一次买开信号位置
  • BARSSK:上一次卖开信号位置
  • BARSSP:上一次卖平信号位置
  • BARSBP:上一次买平信号位置

我们举例示范一下。这里我们使用日志输出上一次买开信号位置和卖平信号位置,根据日志可以看出:在没有执行相应信号之前,这两个函数返回的值是NaN,执行相应信号以后,就开始统计上一次信号执行位置距离当前k线的根数。

MA1^^MA(CLOSE,5);
CROSSUP(C,MA1),BK;
INFO(1,BARSBK,'上一次买开信号位置#FF0000');
C>BKPRICEAV+10||C<BKPRICEAV-10,SP(BKVOL);
INFO(1,BARSSP,'上一次卖平信号位置#00FF00');
TRADE_AGAIN(3);

还有一系列函数可以帮助获取指令信号的位置,成交量和价格,具体包括:

  • REFSIG_PLACE(Sig,N):返回距离当根K线第N个固定的Sig信号的k线数目。
  • REFSIG_VOL(Sig,N):返回从当根K线开始倒数第N个固定的Sig信号的信号手数(反手指令取开仓手数)
  • REFSIG_PRICE(Sig,N):返回从当根K线开始倒数第N个固定的Sig信号的信号价位

这些函数有参数Sig和N,Sig是具体的信号,我们讲过的7个交易指令都可以使用,N是信号的位置。这些函数可以用来判断指定位置的具体指令的具体属性。

  • COUNTSIG(Sig,N):统计N周期内,某一具体信号的数量。信号可以为BK,SK,SP,BP,SPK,BPK,CLOSEOUT。
MA1^^MA(CLOSE,5);
CROSSUP(C,MA1),BK;
C>BKPRICEAV+10||C<BKPRICEAV-10,SP(BKVOL);
INFO(1,REFSIG_PLACE(BK,1),'距离当前k线第一个BK信号的k线数目#FF0000');
INFO(1,REFSIG_VOL(BK,1),'距离当前k线第一个BK信号的开仓手数#FF0000');
INFO(1,REFSIG_PRICE(BK,1),'距离当前k线第一个BK信号的开仓价格#FF0000');
INFO(1,COUNTSIG(BK,3),'N周期内BK信号的数量#0000FF');
TRADE_AGAIN(3);

这里我们举例示范一下,分别使用REFSIG统计当前k线第一个BK信号的k线数目,手数和开仓价格,COUNTSIG统计三周期内BK信号的数量,可以看到,在策略开始,由于没有开仓,仅仅输出COUNTSIG函数的结果;在开仓以后,开始输出REFSIG的具体属性。大家可以根据这类的函数属性,制定一些需要的策略。

头寸函数

接下来我们来介绍一下My语言中的头寸函数,它可以帮助我们实时查看交易账户的资金状态。

  • MYVOL:取下单手数,多用于在加减仓模型加载多个合约的时候的手数计算。这是交易类库中的一个参数,这里我们可以进行修改。
  • MONEY:MONEY返回账户可用资金,用于仓位、手数等计算。
  • MONEYTOT:MONEYTOT返回当前账户权益,模型进行仓位控制、下单手数等资金管理时使用
  • MARGIN:杠杆率

我们编写代码示范一下:

C>1, BK;
INFO(1, MYVOL, '下单手数');
INFO(1, MONEY, '可用资金');
INFO(1, MONEYTOT, '当前账户权益');
INFO(1, MARGIN, '杠杆率');

可以看到,在策略运行开始,返回默认的下单手数和杠杆率,没有开仓所以可以资金和当前账户权益是一致的;开仓以后,可用资金MONEY是初始的金额减去了保证金,加上仓位的盈亏;而当前MONEYTOT是包含保证金在内的,初始的金额加上仓位的盈亏。

交易类库

以上呢,就是My语言中的交易函数。在使用交易函数时,我们不得不提到My语言的交易类库。一个策略并不是仅有策略代码就可以运行的,我们还需要搭建策略运行的环境。这个类库就是脱离策略代码层面的,目的是将策略实际交易过程中所需的数值、参数和模式进行整合封装,从而让我们在回测系统模拟或实盘创建时能够方便地进行设置和配置。通过使用这个框架类库,我们可以更好地进行交易的设置,确保策略的稳定运行。

由于市场是瞬息万变的,策略在运行过程中可能会遇到各种突发情况,导致无法完美执行交易操作。因此,我们需要提前为这些情况做好设置和容错处理。My语言的交易类库正是为了满足这一需求而设计的,它提供了丰富的工具和功能,帮助我们应对市场的挑战。

需要注意的是,这里面有些参数是针对于其他金融市场的,我们使用默认值就好。

交易设置

我们来到回测页面来看下。第一个栏目是“交易设置”,其中的执行方式我们前面讲到过。

默认开仓手数:我们刚才提到过,如果对于BK,SK,BPK,SPK没有指定下单数量参数则按照该参数作为下单数量。

最大单次交易下单量:允许的单次下单的最大数量,如果设置的信号触发时下单量比较大,执行下单时会把订单拆分成小的订单分笔下单。

滑价点数(整数):主要用于设置下单交易吃单时加上或减去的溢价,例如当需要买入时,对手卖一的价格时10,我们下买单价格出11,此时11-10=1,多出的1元差价就是滑价,卖出相反,减价卖出的部分就是滑价,加滑价的目的是为了确保成交。需要注意的是,在商品期货交易中,不同品种有不同的priceTick(即一跳价格),系统会自动获取当前品种的priceTick,此时设置的滑价点数就是priceTick的倍数。

这里呢,也可以解释日志信息里,为什么我们看到这里的价格和下单的价格具有较大的差别,这里其实就是滑价点数。比如这里设置品种为铁矿石,滑价为5,当我们下单的时候,实时的卖一价ask是841,为了确保成交,我们需要使用卖一价ask加上,5乘以铁矿石的priceTick是0.5,等于2.5,所以挂单的价格是841加上2.5,843.5这是一个比较高的挂单价格,可以确保成交,并不是实际的成交价格。

变量最长周期数:保存的数据最长周期数,如果设置该参数为200,那么策略中计算的各种数据序列,例如均线、MACD指标线等,只保存最近200根K线上的数据。

期货设置

品种代码这里直接使用合约代码加上888,表示主力合约;或者代码加上000,表示指数合约,但是在具体交易的时候,回测系统和实盘都会映射到最新的主力合约代码上面,并且也会进行移仓换月的操作。

实盘选项

下单重试次数:下单如果没有成交(例如行情变化很快,滑价设置不大的情况,可能下单时,盘口已经移动了)。撤销订单重新下单,该参数控制重新下单的次数,超过次数不再下单,信号执行完毕。

账户同步时间(秒):读取账户数据的时间间隔。

盈亏统计间隔:My语言的收益统计是按时间间隔定时计算、打印当前的浮动盈亏。

失败重试(毫秒):该参数用于接口调用失败时,间隔多少时间重试。

推送通知:该参数勾选后,下单日志,策略中的推送消息会推送到当前账号设置的推送选项。优宽的推送选项可以在这里设置,点击这里的账号设置,选择推送设置,可以选择将实时的交易信息推送到移动端,邮箱或者webhook。

以上就是交易类库中的一些参数的设置,可以在回测系统和实盘里帮助我们更顺利的执行交易的策略。My语言的函数部分我们已经介绍完毕,听到这里的同学,我相信大家一定有十足的耐心和热情去打开量化交易的大门,从下节课开始,我们将真正的进入量化策略的编写部分,大家不要错过。

八、简单模型编写示例(一)

前面的课程,我们介绍了优宽平台支持的My语言函数,包括实时数据获取,信号指标计算,条件逻辑判断,交易函数等,这些函数基本构建了搭建一个策略需要的主体框架。从本节课开始,我们将从My语言一般模型编写开始,从一行行代码敲起来,打造自己的量化策略。大家在编写模型的过程中,如果遇到哪些问题也欢迎留言,我们也会热心解答。

在本节课中,我们讲解My语言简单模型的编写范例。内容包括K线形态的识别、经典指标的计算,以及常见的趋势类和震荡策略的编写。通过实际示例,我们将帮助大家了解My语言策略的编写逻辑和具体实践过程,为大家手动创建个性化策略提供指导。

K线形态的识别

首先,我们从K线形态的识别帮助大家进行量化策略的入门。K线图是历史和实时价格的趋势反应,通过研究K线的趋势规律,可以在一定程度上预测未来走向,也可以帮助判断多空双方的力量对比,进而为投资决策提供重要的参考。

K线图共有三部分组成:即上影线、下影线和实体三部分,上影线为最高价,下影线为最低价,实体由收盘价和开盘价构成。当收盘价高于开盘价时, 用阳线或红线来表示,当开盘价高于收盘价时,用阴线或黑线来表示。依据K线中开盘价,收盘价,最高价和最低价的关系,我们将K线的常见基本形态进行了不同的分类,具体的分法和命名的方式有很多,比如这里图中展示的十四种。

image

有不少的技术派的朋友都喜欢使用k线判断未来的走势,依靠我们的肉眼去观察各个K线的状态并判断确实需要一定的耐心和经验,而在量化语言的帮助下,我们可以自动的判断各个k线的属性,我们举个例子来看下。

光头光脚

第一类我们来看光头光脚类,这类k线的最高价和最低价,是和k线的收盘价或者开盘价一致的,也就是开盘就是最低价或者最高价,收盘就是最低价或者最高价,我们来看下怎样使用My语言进行判断。

// 光头光脚阳线
POS_HEAD := CLOSE = HIGH;
POS_TAIL := OPEN = LOW;
INFO( POS_HEAD && POS_TAIL, '涨幅',CLOSE/OPEN - 1,'光头光脚阳线');

// 光头光脚阴线
NEG_HEAD := CLOSE = LOW;
NEG_TAIL := OPEN = HIGH;
INFO( NEG_HEAD && NEG_TAIL, '涨幅',CLOSE/OPEN - 1,'光头光脚阴线');

这里首先设置光头光脚阳线,收盘价CLOSE是最高价,开盘价是最低价,在满足两项条件情况下,使用INFO进行输出,并计算了具体的涨幅。于此相反,我们也进行光头光脚阴线统计。

这类行情属于极端行情,我们使用比较有名的妖孽品种纯碱试一下,回测时间是去年的一年,可以看到在8月29号是一个极致的阴线,跌幅是6%,8月30号是一个极致的阳线,涨幅是7%,确实比较极端。可以看到,通过对比开盘价,收盘价,最低价和最高价之间的关系,我们就可以使用程序判断单根k线的不同状态。

以上呢,只是单根k线的形态,如果组合两根或者两根k线以上,总结出来了更多的k线形态。这些K线形态也可以使用量化语言进行鉴别。

image

跳空

跳空是两条相邻K线之间出现价格的大幅上涨或者下跌的情况,包括跳空高开和跳空低开。要问期货市场哪个品种出现的跳空次数最多,相信熟悉期货市场的朋友这个答案可以脱口而出,燃油。燃油的走势依赖于原油,而原油和国外的原油品种存在较大的相关性,但是因为国内外原油品种的开盘时间不同,国外累计的走势需要在国内开盘一瞬间完成,所以就造成燃油期货品种在开盘的一瞬间出现大幅跳空高开或者跳空低开的情况。我们使用My语言进行一下统计。

//跳空高开
PREHIGH := REF(HIGH, 1);
INFO(OPEN > PREHIGH * 1.01, '幅度:',OPEN/REF(CLOSE, 1) - 1,'跳空高开#FF0000');

//跳空低开
PRELOW := REF(LOW, 1);
INFO(OPEN < PRELOW * 0.99, '幅度:',OPEN/REF(CLOSE, 1) - 1,'跳空低开#00FF00');

通过比较两条K线的属性,大家有没有好的思路使用My语言进行定义跳空高开和跳空低开的情况。对了,可以使用REF函数,最新的开盘价大于上一根K线的最高价一定百分比的时候,我们定义为跳空高开;相反情况下,当最新的开盘价小于上一根K线的最低价一定百分比,定义为跳空低开。

这里我们统计跳空高开和跳空低开的情况。如果最新的开盘价大于上一周期的最高价乘以1.01的倍数,我们定义为跳空高开,并计算一下高开的幅度。对于跳空低开,定义开盘价小于上一根k线的最低价乘以0.99,打印低开的幅度。

我们来看一下结果,使用燃油期货,设置k线周期为1小时。可以看到在每天早上开盘9点第一根k线结束,10点的时候;或者晚上21点开盘,K线结束22点的时候,非常容易出现跳空高开和低开的情况,在其他的时间段行情都是比较平稳的。所以,喜欢对冲套利的朋友可以考虑一下燃油期货。

经典指标信号的计算

接下来我们来看下使用My语言进行一些经典指标的编写实例。前面课程在数理函数的讲解课程中,我们进行了MACD指标的编写。其实这些指标并不复杂,在我们了解指标计算原理的基础上,我们基本上都可以使用My语言进行实现。在指标计算的基础上呢,我们可以进行具体的信号判断,比如多头排列,金叉死叉,背离等。

多头排列 vs. 空头排列

多头排列和空头排列是在技术分析中经常用到的概念,它们涉及到市场中多头(买方)和空头(卖方)力量的相对关系。

多头排列具体指的是短期移动平均线在长期移动平均线的上方,这被认为是一个积极的信号,表明价格处于上涨的趋势。而短期移动均线处于长期均线下方的时候,认为价格处于下跌的趋势。

具体的均线周期和数量的选择,可以根据自身对于市场的理解进行决定,这里我们展示一下三均线多头排列和空头排列的My语言程序。

MA5 ^^ MA(CLOSE,5);
MA10 ^^ MA(CLOSE,10);
MA30 ^^ MA(CLOSE,30);
POSLINE := MA5 > MA10 && MA10 > MA30;
NEGLINE := MA5 < MA10 && MA10 < MA30;
INFO(POSLINE, '多头排列#FF0000');
INFO(NEGLINE, '空头排列#00FF00');

这里分别设置三条均线,使用的周期是5,10和30,对于多头排列是短期大于中期,中期大于长期;空头排列刚好相反。

金叉 vs. 死叉

多头排列和空头排列可以判断实时的趋势,可以当我们想判断市场转折点进行入场的时候,金叉和死叉是比较适合的。

"金叉"和"死叉"是技术分析中常用的术语,用来描述两条移动平均线的相对位置关系。金叉发生在短期移动平均线从下方穿越长期移动平均线的时候。通常,这被视为一个买入信号,表明市场由跌势进入上涨趋势。死叉刚好相反,发生在短期移动平均线从上方穿越长期移动平均线的时候,表明市场即将进入下跌趋势。

MA5 ^^ MA(CLOSE,5);
MA10 ^^ MA(CLOSE,10);
MA30 ^^ MA(CLOSE,30);
GOLDCROSS := CROSSUP(MA5, MA10) && CROSSUP(MA10, MA30);
DEADCROSS := CROSSDOWN(MA5, MA10) && CROSSDOWN(MA10, MA30);
INFO(GOLDCROSS, '金叉#FF0000');
INFO(DEADCROSS, '死叉#00FF00');

这里我们定义当短期上穿中期,中期上穿长期的时候,定义为金叉;反之定义为死叉,我们运行一下,发现没有符合条件的k线。这也是可以理解的,因为比较均线同时上穿或者下穿是比较难以满足的,我们可以改变一下代码。对于金叉当短期上穿中期的时候,只需要判断中期是否大于长期就可以;对于死叉当短期下穿中期的时候,需要判断中期是否小于长期。日志输出可以看到对应的金叉和死叉的信号。

MA5 ^^ MA(CLOSE,5);
MA10 ^^ MA(CLOSE,10);
MA30 ^^ MA(CLOSE,30);
GOLDCROSS := CROSSUP(MA5, MA10) && MA10 > MA30;
DEADCROSS := CROSSDOWN(MA5, MA10) && MA10 < MA30;
INFO(GOLDCROSS, '金叉#FF0000');
INFO(DEADCROSS, '死叉#00FF00');

当然上面的只是基本的条件,这里我们还可以发挥主观能动性,添加一些成交量的条件,比如在出现金叉或者死叉的时候,是否成交量或者持仓量出现巨量的上涨或者下跌,大家可以试着判断一下。

顶背离 vs. 底背离

接下来我们来看一个概念背离。在技术分析中,"背离"是指价格走势和某种技术指标之间出现不一致的情况。背离可以分为两类:顶背离和底背离。

顶背离发生在价格创造新高而某个技术指标未能确认新高的情况下。通常,这被视为市场可能趋于疲软的信号。例如,价格形成新的高点,但相对强弱指数(RSI)或移动平均散度收敛指标(MACD)等技术指标未能跟随形成新高,甚至呈现下降趋势。

相对底背离发生在价格创造新低但是某些指标不跟随,甚至呈现上升趋势。因此背离可以作为出场信号的标志,我们使用My语言代码进行一下实现。

FASTLINE^^EMA(CLOSE,12);
SLOWLINE^^EMA(CLOSE,26);
DIF:FASTLINE-SLOWLINE,CIRCLEDOT;
DEA:EMA(DIF,9);
MACDDIFF:2*(DIF-DEA),COLORSTICK, IF(2*(DIF-DEA) > 0, COLORRED, COLORGREEN);
TOPDIV := CLOSE > REF(CLOSE, 1) && MACDDIFF < REF(MACDDIFF, 1);
BOTDIV := CLOSE < REF(CLOSE, 1) && MACDDIFF > REF(MACDDIFF, 1);
INFO(TOPDIV, '顶背离#FF0000');
INFO(BOTDIV, '底背离#00FF00');

我们来看一下My语言的编写,首先使用我们先前讲过的MACD指标,计算MACD值。然后判断背离的情况,顶背离是收盘价大于上根k线的收盘价,也就是价格是上升的,但是MACD小于上根k线的值,定义为顶背离。底背离刚好相反,如果价格转为下降,但是MACD值出现上升,我们定义为底背离。这就是背离的一个基础版的定义。

背离可以作为一个出场的信号,这里我们结合上面的金叉和死叉的概念,在MACD出现金叉或者死叉我们进行入场开仓,出现背离进行相应的离场。这样一个策略的模型我们就搭建完成。我们来试着编写一下。

FASTLINE^^EMA(CLOSE,12);
SLOWLINE^^EMA(CLOSE,26);
DIF:FASTLINE-SLOWLINE,CIRCLEDOT;
DEA:EMA(DIF,9);
MACDDIFF:2*(DIF-DEA),COLORSTICK, IF(2*(DIF-DEA) > 0, COLORRED, COLORGREEN);
TOPDIV := CLOSE > REF(CLOSE, 1) && MACDDIFF < REF(MACDDIFF, 1);
BOTDIV := CLOSE < REF(CLOSE, 1) && MACDDIFF > REF(MACDDIFF, 1);

INFO(TOPDIV, '顶背离#FF0000');
INFO(BOTDIV, '底背离#00FF00');


GOLDCROSS := CROSSUP(MACDDIFF, 0);
DEADCROSS := CROSSDOWN(MACDDIFF, 0);
INFO(GOLDCROSS, '金叉#FF0000');
INFO(DEADCROSS, '死叉#00FF00');

GOLDCROSS, BK;
TOPDIV, SP;
DEADCROSS, SK;
BOTDIV, BP;

AUTOFILTER;

这里我们选择走势比较平稳的玉米品种试一下,可以看到这个策略在去年比较平稳的情况下收益还是不错的。大家可以改编这个策略,添加更多的条件,针对于自己喜欢的品种,进行更多的尝试!

九、简单模型编写示例(二)

上节课我们学习了My语言中K线形态识别,以及一些技术指标的判断,并且最后利用这些技术指标编写了一个量化策略。本节课,我们将聚焦于量化交易中的三种重要策略类型:趋势类、通道类和震荡类策略。在了解这些策略概念的基础上,我们将学会怎样使用My语言进行实现。

趋势类策略

在量化交易中,趋势类策略是一种基于历史价格趋势的模型。通过对市场趋势的识别和预测,我们可以制定策略以追随并利用这些趋势。

趋势类策略在量化交易中具有显著的优点和一些明显的缺陷。首先,其主要优势在于能够较为准确地捕捉市场的明显趋势方向,使得交易者更容易在趋势初现时进入市场,从而获取更大的收益。这使趋势类策略在市场有明确趋势的时候能够灵活适应,并更好地把握市场机会。其适用性广泛,且操作相对简单,特别是使用基础技术指标如移动平均线等进行趋势判断的方法,易于理解和实施。

然而,趋势类策略也存在一些明显的缺陷。首先,受限于价格数据的延迟,特别是在使用长周期均线时,可能导致进场点相对滞后,错过一部分趋势初期的涨跌。在市场处于震荡阶段时,表现可能较差,因为趋势类策略更适用于明显趋势的市场,而在价格波动不明显时容易产生误判和频繁的交易信号。此外,在市场快速变化或出现剧烈波动时,趋势类策略可能无法迅速调整,导致无法灵敏地捕捉到短期内的趋势变化。

综合而言,趋势类策略在趋势明显的市场中表现出色,但在市场变化较为复杂的情况下,可能需要与其他类型的策略结合使用,以提高整体的交易效果。

趋势判断使用最多的技术指标之一就是均线,在前面My语言数理统计函数中,我们学过很多种均线,比如最简单的简单移动平均线(MA),指数移动平均线(EMA),加权移动平均线(WMA)等。这些均线可以通过对不同时间段内的价格数据进行平均计算,形成平滑的趋势线,从而更清晰地揭示市场价格的走势方向。

我们大致来说下这些均线的区别,简单移动平均线(MA)通过计算一定时间内的平均价格,每个价格的权重是一样的,用来平滑价格波动,使趋势更为明显。指数移动平均线(EMA)则更加注重近期价格的权重,对市场变化更为敏感。而加权移动平均线(WMA)则在计算均值时对不同时间点的价格给予不同的权重,更灵活地适应市场的变化。

这些均线不仅用于趋势的确认,还可作为制定买卖信号的依据。例如,上节课我们讲过,当短期均线上穿长期均线时,可能产生“金叉”信号,被视为买入时机;相反,当短期均线下穿长期均线时,可能产生“死叉”信号,被视为卖出时机。这些信号的生成有助于自动化交易决策,提高交易效率。

在制定趋势类策略时,除了均线外,还可以结合其他技术指标如MACD(移动平均散度收敛指标)、ADX(平均动向指数),RSI(随机强弱指标)等,以全面把握市场趋势的方向和强度。综合利用这些指标,我们能够更精准地捕捉并响应市场的趋势,从而实现更有效的量化交易策略。因此本节课我们讲的第一个模型就是均线结合RSI指标的模型。

RSI的原理很简单,就是通过一系列的数学运算,得出商品期货市场中买卖双方的力量强弱对比,从而预测未来价格的趋势方向。RSI指标的数值范围是0~100,但大部分都是在20~80之间波动,如果RSI的值超过80就说明该品种被过度买入,价格转向下跌的趋势较大。如果RSI的值低于20就说明该品种被过度卖出,价格容易出现反弹。RSI的计算过程还是非常简单,一句话可以概括为:在某个时间段价格上涨所产生的波动占整个波动的百分比。

My语言封装了设置期货合约和数据获取的指令,所以我们直接开始指标的计算。首先我们还是利用代码计算RSI指标,首先获取上根K线收盘价,然后计算收盘价与上根K线收盘价的差,在该差值与0之间取最大值,代表上涨的波动;接着计算收盘价与上根K线收盘价的差,取该差值绝对值,代表总体的波动;然后分别计算U和D的2周期平均值,这里的周期大家可以设置;通过计算U和D的比值,将比率乘以100,保证了其值范围在0~100之间,就获取到了RSI的值。然后我们计算EMA指标,这里使用到了内置函数EMA,但是EMA的均值周期这里我们设置为策略的参数。因为固定的参数并不适合于所有的品种,所以这里设置为策略的参数,放进模型中进行调参找到适合不同品种的参数。然后我们就可以计算交易信号了,当形成金叉,收盘价大于EMA均值,RSI小于20,定义为做多信号;反之死叉,并且RSI大于80,定义为做空信号。最后设置AUTOFILTER形成一开一平的交易模式。

// RSI值
YC := REF(C, 1);  // 上根K线收盘价
U := MAX(C - YC, 0);  // 计算收盘价与上根K线收盘价的差,在该差值与0之间取最大值
D := ABS(C - YC);  // 计算收盘价与上根K线收盘价的差,取该差值绝对值
RS := SMA(U, 2, 1) / SMA(D, 2, 1);  // 分别计算U和D的2周期平均值,计算U和D的比值
RSI : RS * 100;  // 将比率乘以100,保证了其值范围在0~100之间

// 均值
EMAVALUE ^^ EMA(CLOSE, meanPeriod);

// 交易操作
CLOSE > EMAVALUE AND RSI < 20, BPK; //平空开多
CLOSE < EMAVALUE AND RSI > 80, SPK; //平多开空
AUTOFILTER;

模型代码写好以后,设置交易品种为玉米,这里重点我们来看下怎样进行调参。设置调参范围是5到30,以5为步长,我们来看下不同参数下的模型收益如何,可以看到,模型在参数为15时,获得了最高的收益。但是我们也不能直接应用于这个参数到实盘当中,我们需要回测更长的时间,检验模型的健壮性。

通道类策略

通道类策略在量化交易中是基于价格波动通道的模型。这种策略认为价格在一定通道内波动属于正常区间,当价格突破边界的时候,进行交易来获取利润,所以可以认为是一个突破策略。因此通道类策略的要点包括:

  1. 通道确定: 利用历史价格数据,通过计算价格的波动范围、支撑与阻力水平等,确定市场的交易通道。

  2. 突破交易: 在价格突破通道底部的时候进行卖出,在价格突破通道顶部进行买入。这要求交易者在波动通道中敏锐地把握价格的波动特征。

  3. 动态调整交易范围: 随着市场波动性的变化,通道的宽度也可能发生变化。因此,通道类策略需要能够动态调整交易通道的范围,以适应市场的变化。

通道类策略相比于一些复杂的量化交易策略,通道类策略较为简单直观。通过对历史价格的波动范围进行分析,可以相对容易地确定交易通道。并且由于基本思想是在价格突破通道时进行交易,执行通道类策略相对较为简单。交易者可以根据事先设定好的规则和参数执行交易。因此通道类策略可以帮助交易者捕捉市场快速波动的机会,从而在较短时间内获取利润。

但是通道类策略也存在一些缺陷,通道类策略的性能高度依赖于市场的波动性,如果市场进入低波动期或高波动期,通道的宽度可能需要调整。这要求策略需要能够敏感地捕捉市场波动性的变化。并且在市场存在噪声时,价格可能会在通道内频繁波动,导致假信号。这可能使得通道类策略容易受到噪声的干扰,执行不准确。

通道类比较著名的策略包括唐奇安通道和布林带通道策略。唐奇安通道使用的是固定周期内的最高价和最低价作为上下轨,当突破上下轨的时候进行买入和卖出的操作。布林带通道是使用一段周期内的价格作为均线,然后波动范围的计算是一段时间内的标准差,然后使用均线加减2倍标准差,作为通道的上下轨,所以通道的宽度更加灵活,可以较快的反应价格变化的趋势。本节课我们就来使用My语言进行布林带通道策略的实现。

首先我们计算均线和标准差,这里使用到了两个策略参数,N1是均线周期,N2是标准差周期,然后我们就可以利用均值加减两倍差作为上限和下限,当收盘价向上突破上限的时候,定义为做多信号;当收盘价下穿下限,定义为做空信号。最后使用两个信号进行开平仓的操作。

//布林带通道
MAVALUE:=MA(CLOSE,N1); //均线
STDVALUE:=STD(CLOSE,N2); //标准差
UPLINE ^^ MAVALUE+2*STDVALUE; //布林带上限
BOTLINE ^^ MAVALUE-2*STDVALUE; //布林带下限

//交易信号
LONGSIG:=CROSSUP(CLOSE,UPLINE);// 平空开多条件
SHORTSIG:=CROSSDOWN(CLOSE,BOTLINE); //平多开空条件

//交易操作
LONGSIG,BPK;
SHORTSIG,SPK;

//过滤函数
AUTOFILTER;

这就是一个简单的布林带策略,当然这个策略也可以进行更多的拓展,比如这里的平仓条件我们可以设置的更加稳妥一点,当最新的收盘价到达均线的时候就进行平仓,不需要等到突破的时候再进行操作。大家可以尝试一下。

震荡类策略

震荡类策略是一种适用于市场无明显趋势的情况下的模型。该策略认为价格会在一定范围内反复震荡,交易者可以在波动的底部买入、在波动的顶部卖出。所以震荡类策略背后的原理是均值回归的思想。所以这和上面的通道突破类策略类似,假设价格波动的范围在一定的区间,但是更多的是假设均值要进行回归。

这种策略的优势在于其相对简单直观,能够捕捉到市场短期内的震荡行为,特别适用于横盘市场。然而,它在面对明显趋势的市场时可能表现较差,容易受到噪声的干扰,而且对于参数的选择相当敏感。此外,由于强调价格回归到均值,可能错过长期趋势行情,需要在使用时谨慎权衡其优缺点,并结合风险管理策略进行合理的参数选择和执行。

所以在上一个通道策略的基础上,我们可以进行修改,将它改变成为一个震荡类策略。大家想下有没有具体的思路。好的,下面我们用代码进行一下实现。

同样的计算出来上轨UPLINE,中轨MAVALUE,下轨DOWNLINE,但是具体开平仓的逻辑我们需要改变一下。当价格下穿下轨的时候,我们预测价格会回归到均值,所以进行开多,所以当价格回归到均值我们进行平多;与此相返,当价格上穿上轨进行做空,直到回归均线,我们进行平空。

但是这个模型面临一个问题,我们能假设价格一直是平稳运行的吗?呈现趋势单边上涨或者下跌行情的时候,我们会面临比较大的亏损。所以我们需要添加一个前置条件,当标准差小于一定阈值,证明最近走势比较平稳我们再进行开仓的操作。所以添加一个前置条件,标准差需要小于一个参数阈值,这里设置为策略参数,在开仓的条件中增加这个标准差的限制条件。这样一个可以避免趋势行情的震荡类策略我们就设置完成。

//布林带
MAVALUE ^^ MA(CLOSE,N1);
STDVALUE:=STD(CLOSE,N2);
UPLINE ^^ MAVALUE+2*STDVALUE;
BOTLINE ^^ MAVALUE-2*STDVALUE;
//交易条件
LONGSIG:=CROSSDOWN(CLOSE,BOTLINE); //开多条件
COVERLONGSIG:=CROSSUP(CLOSE,MAVALUE);//平多条件
SHORTSIG:=CROSSUP(CLOSE,UPLINE);// 开空条件
COVERSHORTSIG:=CROSSDOWN(CLOSE,MAVALUE); //平空条件
//交易系统:
STDVALUE < STDTHRE && LONGSIG,BK;
COVERLONGSIG,SP;
STDVALUE < STDTHRE && SHORTSIG,SK;
COVERSHORTSIG,BP;
//过滤函数
AUTOFILTER;

在量化交易中,趋势类、通道类和震荡类策略各具特色,适用于不同的市场状况。有效的量化模型需要结合市场数据、技术指标和风险管理,灵活运用这些策略,这样呢才可以在复杂多变的市场环境中取得稳健的交易收益。

十、My语言商品期货量化交易教程:复杂模型编写示例(一)

上节课程我们讲解了My语言中简单模型的编写示范,在讲解的简单模型当中,使用的大多数都是单一K线周期的,单个或者两个指标的策略模型。但是在实际的交易中,市场变化复杂,很难使用简单的模型去模拟所有的市场变化,所以更多的时候,我们需要多个周期,多个指标去判断市场的趋势,并且在交易过后,我们需要止盈止损的措施在获取更多收益的同时,及时止损,防止扛单等遭受更多损失的风险管理措施。这样才是一个合乎标准的实盘级策略。本节课程,我们就来讲解复杂模型的编写示例。

麦语言与JavaScript语言混合编程

在My语言课程导入部分我们有提到过,在优宽平台,量化策略可以在My语言的基础上,还可以召唤JavaScript大法,自定义功能模块,帮助复杂模型中指标的获取和计算。下面我们来看下怎样操作。

我们来举一个在My语言中使用Js自定义功能模块的例子。

%%
scope.TEST = function(obj) {
    return obj.val * 100;
}
%%
收盘价:C;
收盘价放大100倍:TEST(C);
上一个收盘价放大100倍:TEST(REF(C, 1)); 

INFO(1, 收盘价, '收盘价');
INFO(1, 收盘价放大100倍, '收盘价放大100倍');
INFO(1, 上一个收盘价放大100倍, '上一个收盘价放大100倍');

首先我们需要%%符号定义Js功能模块,这里面可以调用优宽量化的任何API。这里面scope是一个对象,可以添加属性,比如这里我们添加TEST函数为scope的一个属性。在这个TEST函数里,参数是obj,返回结果是obj.val的100倍结果。

接着在My语言代码部分就可以调用这个属性引用的匿名函数。比如这里定义第一个变量是收盘价,然后使用Js模块中的TEST函数获取收盘价的100倍,最后一个变量也是使用TEST,但是参数是上一个收盘价。然后我们使用INFO函数打印出来函数返回的结果。可以在日志里,我们可以看到返回了相应的结果。

这就是在My语言中使用Js自定义功能模块的一个简单例子。除了自定义属性,这里的scope对象还由一些固定的属性,这里给大家讲解一下。

  • scope.getRefs(obj)

第一个getRefs,调用scope.getRefs(obj)会返回传入的obj对象的数据。这里我们举例定义TEST2函数,在这个函数内,参数是obj,使用arr定义getRefs返回的结果,然后使用log进行打印。在My语言当中,使用TEST2函数,当填写参数为收盘价的时候,TEST2函数会返回这个K线数据的所有的收盘价。但是由于使用了throw "stop"中断程序。所以返回结果变量arr只包含了第一根Bar的收盘价。

%%
scope.TEST2 = function(obj){
    var arr = scope.getRefs(obj)
    Log("arr:", arr)
    throw "stop"
    return
}
%%
TEST2(C);
  • scope.bars

Scope.bars在JavaScript代码块中访问所有K线bar。这里我们定义TEST3函数,当我们想要判断最新的一根K线,所以它的索引位置是bars.length - 1,判断它的开盘价是否大于收盘价,也就是当前是否是阴线。如果是,返回数值1,如果不是返回数值0。根据回测结果,可以看到返回相应的阴线判断。

%%
scope.TEST3 = function(){
    var bars = scope.bars
    return bars[bars.length - 1].Open > bars[bars.length - 1].Close ? 1 : 0    // 只能返回数值
}
%%
//arr:TEST3;   
//arr:TEST3();   
INFO(1, arr, 'TEST3结果');   

这里需要注意的一点是,因为TEST3是不包括参数的,所以使用TEST3加上括号的形式,会直接报错。

相对于scope.bars返回所有k线,scope.bar只返回当前k线。

%%
scope.TEST4 = function(){
    var bar = scope.bar
    return bar.Open > bar.Close ? 1 : 0 
}
%%
avg^^TEST4;
INFO(1, arr, 'TEST4结果');  

这里同样的判断当前K线开盘价是否大于收盘价,可以看到和上面返回一致的结果。

  • scope.symbol 返回当前交易品种名称字符串。

  • scope.canTrade 标记当前是否可以交易

以上的就是麦语言与JavaScript语言混合编程的例子,相对而言,Js语言更加灵活,可以实现更多的功能。如果大家熟悉Js语言,在My语言中我们可以编写更多简便的函数,帮助更好的进行策略的实现。

%%
scope.MACD = function(){
    var MACD = TA.MACD(scope.bars, 12, 26, 9)
    return MACD[2][scope.bars.length - 1]
}
%%
MACDVALUE:MACD; //返回MACD最新值
INFO(1, MACDVALUE, 'MACDVALUE');

这里我们示范一个计算MACD的例子,在My语言中,由于不包含MACD的内置函数,所以我们需要手动的进行计算。而在优宽的Js语言当中,对于MACD内置函数进行了封装,所以我们可以直接调用。这里在Js功能块中,使用内置函数TA.MACD,参数填写K线scope.bars,具体的周期设置为12


更多内容