期貨軟件TB系統(tǒng)源代碼解讀系列11-基于ADX及EMA的交易系統(tǒng)

  平均趨向ADX指標是我喜歡觀察的一個好指標,它是輔助我判斷是否有趨勢運動的關鍵性指標,大家可以對它很熟悉了,我也不再這里細說什么了,這次直接解讀TB系統(tǒng)里編寫的基于ADX及EMA的交易系統(tǒng),當然我對交易結果感覺一般,所以后面按我個人意愿,給它改了一下,變成一個新的系統(tǒng)。

  我改寫的系統(tǒng)暫且放下,先來看這TB系統(tǒng)操作的規(guī)則要素:

  1. 計算30根k線最高價和最低價的EMA價差;

  2. 計算12根k線的ADX.

  入場條件:

  1.滿足上根K線的收盤價收于EMA30之上,且ADX向上的條件 在EntryBarBAR內(nèi)該條件成立;

  2.當前價大于等于BuySetup,做多,當條件滿足超過EntryBarBAR后,取消入場.

  出場條件:

  1.當前價格下破30根K線最高價的EMA.

  好了,讓我們來看看這系統(tǒng)編寫的程序化代碼及解讀:(個人覺得那些參數(shù)名,變量名可以跳過,直接讀正文好的,要不然這一大堆的參數(shù)名,變量名誰能記得住的,我都是用的時候返回來寫的)

  Params

  Numeric DMI_N(14); //聲明數(shù)值型參數(shù)名DMI_N,初始值為14.//

  Numeric DMI_M(30); //聲明數(shù)值型參數(shù)名DMI_M,初始值為30.//

  Numeric AvgLen(30); //聲明數(shù)值型參數(shù)名為AvgLen,初始值為30.//

  Numeric EntryBar(2);//聲明數(shù)值型參數(shù)名為EntryBar,初始值為2.//

  Vars

  //DMI最終算出結果需要的變量名。//

  NumericSeries oDMIPlus;//聲明數(shù)值序列變量名為oDMIPlus.//

  NumericSeries oDMIMinus;//聲明數(shù)值序列變量名為oDMIMinus.//

  NumericSeries oDMI;//聲明數(shù)值序列變量名為oDMI.//

  NumericSeries oADX;//聲明數(shù)值序列變量名為oADX.//

  NumericSeries oADXR;//聲明數(shù)值序列變量名為oADXR.//

  NumericSeries oVolty;//聲明數(shù)值序列變量名為oVolty.//

  //DMI過程計算中需要的變量名。//

  NumericSeries sDMI;//聲明數(shù)值序列變量名sDMI.//

  NumericSeries sADX;//聲明數(shù)值序列變量名sADX.//

  NumericSeries cumm;//聲明數(shù)值序列變量名cumm。//

  NumericSeries sVolty;//聲明數(shù)值序列變量名sVilty。//

  Numeric PlusDM;//聲明數(shù)值變量名PlusDM。//

  Numeric MinusDM;//聲明數(shù)值變量名MinusDM。//

  Numeric UpperMove;//聲明數(shù)值變量名UpperMove。//

  Numeric LowerMove;//聲明數(shù)值變量名LowerMove。//

  Numeric SumPlusDM(0);//聲明數(shù)值變量名SumPlusDM,賦值為0.//

  Numeric SumMinusDM(0);//聲明數(shù)值變量名SumMinusDM,賦值為0.//

  Numeric SumTR(0);//聲明數(shù)值變量名SumTR,賦值為0.//

  NumericSeries AvgPlusDM;//聲明數(shù)值序列變量名AvgPlusDM.//

  NumericSeries AvgMinusDM;//聲明數(shù)值序列變量名AvgMinusDM.//

  Numeric SF;//聲明數(shù)值變量名SF。//

  Numeric Divisor;聲明數(shù)值變量名Divisor。//

  Numeric i;//聲明數(shù)值變量名i。//

  NumericSeries TRValue;//聲明數(shù)值序列變量名TRValue。//

  //計算EMA用的變量名。//

  NumericSeries UpperMA(0); //聲明數(shù)值序列變量UpperMA,賦值為0.//

  NumericSeries LowerMA(0); //聲明數(shù)值序列變量LowerMA,賦值為0.//

  NumericSeries ADXValue(0); //聲明數(shù)值序列變量ADXValue,賦值為0.//

  NumericSeries ChanSpread(0); //聲明數(shù)值序列變量ChanSpread,賦值為0.//

  Bool BuySetup(False); //聲明布爾型變量名BuySetup,初始判斷為假。//

  NumericSeries BuyTarget(0); //聲明數(shù)值變量名BuyTarget,賦值為0.//

  NumericSeries MROBS(0); //聲明數(shù)值變量名MROBS,賦值為0.//

  BoolSeries Con1;//聲明布爾型序列變量名Con1.//

  Numeric Minpoint;//聲明數(shù)值型變量名Minpoint。//

  Begin

  If(!CallAuctionFilter()) Return;// 集合競價和小節(jié)休息過濾。//

  Minpoint=Minmove*PriceScale;//這兩句一般固定的直接調(diào)用就行,一個過濾,一個計算最小變動價位。//

  //DMI指標計算, 最終將輸出ADX指標//

  //--------------------------DMI計算開始-----------------------------------//

  SF = 1/DMI_N;//變量SF是一個隨周期而變化的系數(shù),根據(jù)上面的賦值,可以直接得出SF=1/14。//

  TRValue = TrueRange; //變量TRValue值,直接調(diào)用以前我們解讀過的求真實波動函數(shù)TrueRange的值。//

  If(CurrentBar == DMI_N)//假如當前k線數(shù)位等于14,按照下列語句來計算。//

  {

  For i = 0 To DMI_N - 1//循環(huán)語句,就是下列計算方程 i 值從0-13給它計算一遍。//

  {

  PlusDM = 0 ;//先直接等于0了//

  MinusDM = 0 ;//先等于0//

  UpperMove = High[i] - High[ i + 1 ] ;//開始從UpperMove = 最高價High[0]-最高價High[1],一直計算到High[13]-High[14],相當于反復算了14次//

  LowerMove = Low[ i + 1 ] - Low[i] ;//同上的,算這變量LowerMove,也來14次,但記住了,循環(huán)計算也是按照順序邏輯來的,就像我們小學記的九九乘法表那樣,先把1乘以到9,再2乘以到9,程序也是這么一步步按語句來讀的,所以從這FOR下邊的這花括號反復計算,當條件不滿足了,才直接就跳過這括號,接著讀下面的。//

  If (UpperMove > LowerMove and UpperMove > 0 )//假如算得的變量UpperMove大于LowerMove,而且UpperMove大于0.//

  {

  PlusDM = UpperMove;//變量PlusDM就等于變量UpperMove值。//

  }Else if (LowerMove > UpperMove and LowerMove > 0)//并列語句,當條件變成這樣的時候,變量LowerMove大于變量UpperMove值,而且LowerMove大于0.//

  {

  MinusDM = LowerMove ;//變量MinusDM值等于變量LowerMove值。//

  }

  SumPlusDM = SumPlusDM + PlusDM ;//累加起來的意思,從變量SumPlusDM等于0逐步加上計算所得的PlusDM值。//

  SumMinusDM = SumMinusDM + MinusDM ;//同上解讀,這個是累加變量SumMinusDM總值。//

  SumTR = SumTR + TRValue[i] ;//同上,把真實波動值計算出來,累加到變量SumTR總值里。//

  }

  AvgPlusDM = SumPlusDM / DMI_N ;//變量AvgPlusDM值等于變量SumPlusDM總值除以周期數(shù)14.//

  AvgMinusDM = SumMinusDM / DMI_N ;//同上的解讀。//

  sVolty = SumTR / DMI_N ;//同上解讀的。//

  }//循環(huán)到這只要還在0-13里的,就往回重新算一次,直到條件不滿足了,才開始讀下列語句。//

  Else if(CurrentBar > DMI_N)//看著明白了吧,當k線數(shù)位大于了周期數(shù)14.就是上邊循環(huán)跳出來了,開始執(zhí)行下列語句。//

  {

  PlusDM = 0 ;//先等于0.你要問我那14根k線里循環(huán)計算得到的變量PlusDM值呢?我只能跟你說,那個值是針對前14根k線計算的,但是從第15根到開始一直到當前跳動的K線,變量PlusDM都是從0新算起。//

  MinusDM = 0 ; //同上解讀的。先等于0.//

  UpperMove = High - High[1] ;//變量UpperMove值等于當前的最高價減去前一個的最高價。//

  LowerMove = Low[1] -Low ;//變量LowerMove值等于前一個最低價減去當前的最低價。//

  If (UpperMove > LowerMove and UpperMove > 0 )//假如了UpperMove大于LowerMove,并且大于0的。//

  {

  PlusDM = UpperMove;//把變量UpperMove值賦值給變量PlusDM,變成一個新值了,這時不再等于0了。//

  }Else if (LowerMove > UpperMove and LowerMove > 0 )//假如LowerMove大于UpperMove,并且大于0的。//

  {

  MinusDM = LowerMove ;//也是賦予變量MinusDM新的值,即等于變量LowerMove值。//

  }

  AvgPlusDM = AvgPlusDM[1] + SF * ( PlusDM - AvgPlusDM[1] ) ;//照公式直接解讀,變量AvgPlusDM[1]意思是前一個,對第15根k線來說,就是前14根k線算得的值。所以記住這[1]就是從當前數(shù)位倒退一個數(shù)位的意思。//

  AvgMinusDM = AvgMinusDM[1] + SF * ( MinusDM - AvgMinusDM[1] ) ;//這個也直接照公式解讀了。//

  sVolty = sVolty[1] + SF * ( TRValue - sVolty[1] ) ;//同上的,直接照公式解讀。//

  }

  Else//其實這最后這個else就是上面CurrentBar不是大于或等于14時,那就是小于14了,執(zhí)行下列語句,變量都是返回無效值的。//

  {

  oDMIPlus = InvalidNumeric;//返回無效值。//

  oDMIMinus = InvalidNumeric;//返回無效值。//

  oDMI = InvalidNumeric;//返回無效值。//

  oADX = InvalidNumeric;//返回無效值。//

  oADXR = InvalidNumeric;//返回無效值。//

  oVolty = InvalidNumeric;//返回無效值。//

  }

  If (sVolty > 0)//假如計算得的變量sVolty值大于0.//

  {

  oDMIPlus = 100 * AvgPlusDM / sVolty ;//變量0DMIPlus = 100 * 變量AvgPlusDM / 變量sVolty。//

  oDMIMinus = 100 * AvgMinusDM / sVolty ;//直接照公式解讀了。//

  }Else//這就是假如當變量sVolty小于0時。//

  {

  oDMIPlus = 0 ;//變量oDMIPlus=0.//

  oDMIMinus = 0 ;//變量oDMIMinus=0.//

  }

  Divisor = oDMIPlus + oDMIMinus ;//變量Divisor =變量oDMIPlus +變量oDMIMinus//

  if (Divisor > 0)//假如算得的變量Divisor值大于0的。//

  {

  sDMI = 100 * Abs( oDMIPlus - oDMIMinus ) / Divisor; //函數(shù)Abs()意思是返回參數(shù)的絕對值,通俗的說不管括號里計算得到的是大于還是小于0,它返回的都是正整數(shù)。所以照公式解讀,算出變量sDMI值了。//

  }else//假如算得的變量Divisor小于0的。//

  {

  sDMI = 0 ;//變量sDMI等于0.//

  }

  cumm=Cum( sDMI );//函數(shù)Cum(),意思是求累計值,所以這個Cum( sDMI )就是計算從第一個k線以來sDMI值的累計值,把它賦值給變量cumm的。//

  If(CurrentBar > 0)//假如k線數(shù)位大于0的,其實就是從第二根開始了。//

  {

  If (CurrentBar <= DMI_N)//這里再給個限定條件,k線數(shù)位小于或等于周期數(shù)14的。//

  {

  sADX = Cumm / CurrentBar ;//變量sADX等于變量Cumm值除以k線數(shù)位值的。//

  oADXR = ( sADX + sADX[ CurrentBar - 1 ] ) * 0.5 ;//變量oADXR = (變量sADX + 變量sADX[k線數(shù)位值-1])* 固定系數(shù)0.5//

  }Else//這個呢就是假如CurrentBar大于14的。//

  {

  sADX = sADX[1] + SF * ( sDMI - sADX[1] ) ;//變量sADX又是一個新算法,直接照公式來解讀了。//

  oADXR = ( sADX + sADX[ DMI_M - 1 ] ) * 0.5 ;//同樣的,照公式算出新的oADXR值。//

  }

  }

  oVolty = sVolty;//變量oVolty = 變量sVolty。//

  oDMI = sDMI;//變量oDMI = 變量sDMI。//

  oADX = sADX;//變量oADX = 變量sADX。//

  //--------------------------DMI計算結束-----------------------------------//

  ADXValue = oADX; //變量ADXValue = 變量 oADX,其實這就是ADX均線了。//

  UpperMA = XAverage(High, AvgLen); //計算30根K線最高價的EMA。//

  LowerMA = XAverage(Low, AvgLen); //計算30根K線最低價的EMA。//

  ChanSpread = (UpperMA - LowerMA) / 2; //通過EMA計算出通道寬度。//

  BuySetup = Close > UpperMA and ADXValue > ADXValue[1]; //當ADX向上且當前價大于30根K線最高價的EMA滿足買入準備條件。//

  IF (BuySetup )//假如滿足買入條件了,執(zhí)行下列語句。//

  {

  BuyTarget = Close + ChanSpread; //滿足買入準備條件時,用當前k線價格計算出多頭觸發(fā)價,即為當前價 + 通道值。//

  }

  MROBS = NthCon(BuySetup, 1); //上次滿足買入準備條件距離當前k線的距離數(shù)目 .//

  If(MROBS > EntryBar) //假如這個距離數(shù)目大于參數(shù)EntryBar初值2的。//

  {

  MROBS = 0; //距離上次買入準備條件超過參數(shù)ENTRYBAR的數(shù)目后,重置。//

  }

  //系統(tǒng)入場條件。//

  IF( MROBS[1] <> 0 and MarketPosition == 0 and CurrentBar > 100) //滿足買入準備條件后,在ENTRYBAR數(shù)目內(nèi),且大于等于買入多頭觸發(fā)價,多單入場。//

  {

  If(High >= BuyTarget[1] And Vol > 0)//高價突破變量BuyTarget[1],而且成交量大于0的。//

  {

  Buy(0,max(Open,BuyTarget[1]));//取最大值開盤價買入1手。//

  }

  }

  //系統(tǒng)出場條件。//

  If(MarketPosition==1 and BarsSinceEntry >0 And Vol > 0) //當持有多單且當前價格下破30根K線最高價的EMA,多單出場。//

  {

  If(Low <= UpperMA[1] - Minpoint )//低價小于或者等于UpperMA[1] - 最小變動價Minpoint。//

  {

  Sell(0,min(Open,UpperMA[1] - minpoint));//取最小值賣出平倉。//

  }

  }

  End

  很一般,再看賣空的代碼其實都差不多,就是改一下條件,代碼及結果如下:

  Params

  Numeric DMI_N(14);

  Numeric DMI_M(30);

  Numeric AvgLen(30);

  Numeric EntryBar(2);

  Vars

  NumericSeries oDMIPlus;

  NumericSeries oDMIMinus;

  NumericSeries oDMI;

  NumericSeries oADX;

  NumericSeries oADXR;

  NumericSeries oVolty;

  NumericSeries sDMI;

  NumericSeries sADX;

  NumericSeries cumm;

  NumericSeries sVolty;

  Numeric PlusDM;

  Numeric MinusDM;

  Numeric UpperMove;

  Numeric LowerMove;

  Numeric SumPlusDM(0);

  Numeric SumMinusDM(0);

  Numeric SumTR(0);

  NumericSeries AvgPlusDM;

  NumericSeries AvgMinusDM;

  Numeric SF;

  Numeric Divisor;

  Numeric i;

  NumericSeries TRValue;

  NumericSeries UpperMA(0);

  NumericSeries LowerMA(0);

  NumericSeries ADXValue(0);

  NumericSeries ChanSpread(0);

  Bool SellSetup(False);

  NumericSeries SellTarget(0);

  NumericSeries MROSS(0);

  Numeric Minpoint;

  Begin

  // 集合競價和小節(jié)休息過濾

  If(!CallAuctionFilter()) Return;

  Minpoint=Minmove*PriceScale;

  //--------------------------DMI計算開始-----------------------------------//

  SF = 1/DMI_N;

  TRValue = TrueRange;

  If(CurrentBar == DMI_N)

  {

  For i = 0 To DMI_N - 1

  {

  PlusDM = 0 ;

  MinusDM = 0 ;

  UpperMove = High[i] - High[ i + 1 ] ;

  LowerMove = Low[ i + 1 ] - Low[i] ;

  If (UpperMove > LowerMove and UpperMove > 0 )

  {

  PlusDM = UpperMove;

  }Else if (LowerMove > UpperMove and LowerMove > 0)

  {

  MinusDM = LowerMove ;

  }

  SumPlusDM = SumPlusDM + PlusDM ;

  SumMinusDM = SumMinusDM + MinusDM ;

  SumTR = SumTR + TRValue[i] ;

  }

  AvgPlusDM = SumPlusDM / DMI_N ;

  AvgMinusDM = SumMinusDM / DMI_N ;

  sVolty = SumTR / DMI_N ;

  }Else if(CurrentBar > DMI_N)

  {

  PlusDM = 0 ;

  MinusDM = 0 ;

  UpperMove = High - High[1] ;

  LowerMove = Low[1] -Low ;

  If (UpperMove > LowerMove and UpperMove > 0 )

  {

  PlusDM = UpperMove;

  }Else if (LowerMove > UpperMove and LowerMove > 0 )

  {

  MinusDM = LowerMove ;

  }

  AvgPlusDM = AvgPlusDM[1] + SF * ( PlusDM - AvgPlusDM[1] ) ;

  AvgMinusDM = AvgMinusDM[1] + SF * ( MinusDM - AvgMinusDM[1] ) ;

  sVolty = sVolty[1] + SF * ( TRValue - sVolty[1] ) ;

  }Else

  {

  oDMIPlus = InvalidNumeric;

  oDMIMinus = InvalidNumeric;

  oDMI = InvalidNumeric;

  oADX = InvalidNumeric;

  oADXR = InvalidNumeric;

  oVolty = InvalidNumeric;

  }

  If (sVolty > 0)

  {

  oDMIPlus = 100 * AvgPlusDM / sVolty ;

  oDMIMinus = 100 * AvgMinusDM / sVolty ;

  }Else

  {

  oDMIPlus = 0 ;

  oDMIMinus = 0 ;

  }

  Divisor = oDMIPlus + oDMIMinus ;

  if (Divisor > 0)

  {

  sDMI = 100 * Abs( oDMIPlus - oDMIMinus ) / Divisor;

  }else

  {

  sDMI = 0 ;

  }

  cumm=Cum( sDMI );

  If(CurrentBar > 0)

  {

  If (CurrentBar <= DMI_N)

  {

  sADX = Cumm / CurrentBar ;

  oADXR = ( sADX + sADX[ CurrentBar - 1 ] ) * 0.5 ;

  }Else

  {

  sADX = sADX[1] + SF * ( sDMI - sADX[1] ) ;

  oADXR = ( sADX + sADX[ DMI_M - 1 ] ) * 0.5 ;

  }

  }

  oVolty = sVolty;

  oDMI = sDMI;

  oADX = sADX;

  //PlotNumeric("oADX",oADX);

  //--------------------------DMI計算結束-----------------------------------//

  ADXValue = oADX;

  UpperMA = XAverage(High, AvgLen);

  LowerMA = XAverage(Low, AvgLen);

  ChanSpread = (UpperMA - LowerMA) / 2;

  SellSetup = Close < LowerMA and ADXValue > ADXValue[1]; //當ADX向上且當前價下于30根K線最低價的EMA滿足賣出準備條件。//

  If (SellSetup)

  {

  SellTarget = Close - ChanSpread; //滿足賣出準備條件時,用前bar價格計算出空頭觸發(fā)價。//

  }

  MROSS = NthCon(SellSetup, 1); //上次滿足賣出準備條件距離當前BAR的數(shù)目//

  If(MROSS > EntryBar)

  {

  MROSS = 0; //距離上次賣出準備條件超過ENTRYBAR的數(shù)目后,重置//

  }

  //系統(tǒng)入場規(guī)則//

  If( MROSS[1] <>0 and MarketPosition == 0 and CurrentBar > 100) //滿足賣出準備條件后ENTRYBAR數(shù)目內(nèi),且小于等于空頭觸發(fā)價,空單入場 //

  {

  If(Low <= SellTarget[1] And Vol > 0)

  {

  Sellshort(0,Min(Open,SellTarget[1]));

  }

  }

  //系統(tǒng)出場規(guī)則//

  If(MarketPosition==-1 and BarsSinceEntry >0 And Vol > 0) //當持有空單且當前價格上破30根K線最低價的EMA,多單出場//

  {

  If(High >= LowerMA[1] + minpoint )

  {

  BuyToCover(0,max(Open,LowerMA[1] + minpoint));

  }

  }

  End

  看這做空的,多差的收益,所以我就照著心中想的,買賣規(guī)則很簡單,兩條移動均價,ADX值大于25的,兩均線交叉的買入;ADX大于25,兩均線交叉賣出。代碼及結果如下:

  Params

  Numeric DMI_N(14);

  Numeric DMI_M(30);

  Numeric AvgLen(30);

  Numeric FastLength(5);

  Numeric SlowLength(20);

  Numeric TrailingStart1(50); // 跟蹤止盈啟動設置1//

  Numeric TrailingStart2(80); // 跟蹤止盈啟動設置2//

  Numeric TrailingStop1(30); // 跟蹤止盈設置1//

  Numeric TrailingStop2(20); // 跟蹤止盈設置2//

  Numeric StopLossSet(30); //固定止損30個點//

  Vars

  NumericSeries oDMIPlus;

  NumericSeries oDMIMinus;

  NumericSeries oDMI;

  NumericSeries oADX;

  NumericSeries oADXR;

  NumericSeries oVolty;

  NumericSeries sDMI;

  NumericSeries sADX;

  NumericSeries cumm;

  NumericSeries sVolty;

  Numeric PlusDM;

  Numeric MinusDM;

  Numeric UpperMove;

  Numeric LowerMove;

  Numeric SumPlusDM(0);

  Numeric SumMinusDM(0);

  Numeric SumTR(0);

  NumericSeries AvgPlusDM;

  NumericSeries AvgMinusDM;

  Numeric SF;

  Numeric Divisor;

  Numeric i;

  NumericSeries TRValue;

  Numeric Minpoint;

  NumericSeries AvgValue1;

  NumericSeries AvgValue2;

  NumericSeries HighestAfterEntry;

  NumericSeries LowestAfterEntry;

  Numeric MyEntryPrice;

  Numeric myprice;

  Numeric myexitprice;

  Begin

  AvgValue1 = AverageFC(Close,FastLength);

  AvgValue2 = AverageFC(Close,SlowLength);

  PlotNumeric("MA1",AvgValue1);

  PlotNumeric("MA2",AvgValue2);

  If(!CallAuctionFilter()) Return;

  Minpoint=Minmove*PriceScale;

  //--------------------------DMI計算開始-----------------------------------//

  SF = 1/DMI_N;

  TRValue = TrueRange;

  If(CurrentBar == DMI_N)

  {

  For i = 0 To DMI_N - 1

  {

  PlusDM = 0 ;

  MinusDM = 0 ;

  UpperMove = High[i] - High[ i + 1 ] ;

  LowerMove = Low[ i + 1 ] - Low[i] ;

  If (UpperMove > LowerMove and UpperMove > 0 )

  {

  PlusDM = UpperMove;

  }Else if (LowerMove > UpperMove and LowerMove > 0)

  {

  MinusDM = LowerMove ;

  }

  SumPlusDM = SumPlusDM + PlusDM ;

  SumMinusDM = SumMinusDM + MinusDM ;

  SumTR = SumTR + TRValue[i] ;

  }

  AvgPlusDM = SumPlusDM / DMI_N ;

  AvgMinusDM = SumMinusDM / DMI_N ;

  sVolty = SumTR / DMI_N ;

  }Else if(CurrentBar > DMI_N)

  {

  PlusDM = 0 ;

  MinusDM = 0 ;

  UpperMove = High - High[1] ;

  LowerMove = Low[1] -Low ;

  If (UpperMove > LowerMove and UpperMove > 0 )

  {

  PlusDM = UpperMove;

  }Else if (LowerMove > UpperMove and LowerMove > 0 )

  {

  MinusDM = LowerMove ;

  }

  AvgPlusDM = AvgPlusDM[1] + SF * ( PlusDM - AvgPlusDM[1] ) ;

  AvgMinusDM = AvgMinusDM[1] + SF * ( MinusDM - AvgMinusDM[1] ) ;

  sVolty = sVolty[1] + SF * ( TRValue - sVolty[1] ) ;

  }Else

  {

  oDMIPlus = InvalidNumeric;

  oDMIMinus = InvalidNumeric;

  oDMI = InvalidNumeric;

  oADX = InvalidNumeric;

  oADXR = InvalidNumeric;

  oVolty = InvalidNumeric;

  }

  If (sVolty > 0)

  {

  oDMIPlus = 100 * AvgPlusDM / sVolty ;

  oDMIMinus = 100 * AvgMinusDM / sVolty ;

  }Else

  {

  oDMIPlus = 0 ;

  oDMIMinus = 0 ;

  }

  Divisor = oDMIPlus + oDMIMinus ;

  if (Divisor > 0)

  {

  sDMI = 100 * Abs( oDMIPlus - oDMIMinus ) / Divisor;

  }else

  {

  sDMI = 0 ;

  }

  cumm=Cum( sDMI );

  If(CurrentBar > 0)

  {

  If (CurrentBar <= DMI_N)

  {

  sADX = Cumm / CurrentBar ;

  oADXR = ( sADX + sADX[ CurrentBar - 1 ] ) * 0.5 ;

  }Else

  {

  sADX = sADX[1] + SF * ( sDMI - sADX[1] ) ;

  oADXR = ( sADX + sADX[ DMI_M - 1 ] ) * 0.5 ;

  }

  }

  oVolty = sVolty;

  oDMI = sDMI;

  oADX = sADX;

  If(MarketPosition <>1 && AvgValue1[1] > AvgValue2[1] && oADX[1] > 25)

  {

  Buy(1,Open);

  }

  If(MarketPosition <>-1 && AvgValue1[1] < AvgValue2[1] && oADX[1]>25)

  {

  SellShort(1,Open);

  }

  If(BarsSinceentry == 0)

  {

  HighestAfterEntry = Close;

  LowestAfterEntry = Close;

  If(MarketPosition <> 0)

  {

  HighestAfterEntry = Max(HighestAfterEntry,AvgEntryPrice); // 開倉的Bar,將開倉價和當時的收盤價的較大值保留到HighestAfterEntry//

  LowestAfterEntry = Min(LowestAfterEntry,AvgEntryPrice); // 開倉的Bar,將開倉價和當時的收盤價的較小值保留到LowestAfterEntry//

  }

  }else

  {

  HighestAfterEntry = Max(HighestAfterEntry,High); // 記錄下當前Bar的最高點,用于下一個Bar的跟蹤止損判斷//

  LowestAfterEntry = Min(LowestAfterEntry,Low); // 記錄下當前Bar的最低點,用于下一個Bar的跟蹤止損判斷//

  }

  Commentary("HighestAfterEntry="+Text(HighestAfterEntry));

  Commentary("LowestAfterEntry="+Text(LowestAfterEntry));

  Commentary("MyEntryPrice="+Text(MyEntryPrice));

  MinPoint = MinMove*PriceScale;

  MyEntryPrice = AvgEntryPrice;

  If(MarketPosition==1) // 有多倉的情況//

  {

  If(HighestAfterEntry[1] >= MyEntryPrice + TrailingStart2*MinPoint) // 第二級跟蹤止損的條件表達式//

  {

  If(Low <= HighestAfterEntry[1] - TrailingStop2*MinPoint)

  {

  MyExitPrice = HighestAfterEntry[1] - TrailingStop2*MinPoint;

  Sell(0,MyExitPrice);

  }

  }else if(HighestAfterEntry[1] >= MyEntryPrice + TrailingStart1*MinPoint)// 第一級跟蹤止損的條件表達式//

  {

  If(Low <= HighestAfterEntry[1] - TrailingStop1*MinPoint)

  {

  MyExitPrice = HighestAfterEntry[1] - TrailingStop1*MinPoint ;

  Sell(0,MyExitPrice);

  }

  }else if(Low <= MyEntryPrice - StopLossSet*MinPoint)//可以在這里寫上初始的止損處理//

  {

  MyExitPrice = MyEntryPrice - StopLossSet*MinPoint;

  Sell(0,MyExitPrice);

  }

  }else if(MarketPosition==-1) // 有空倉的情況//

  {

  If(LowestAfterEntry[1] <= MyEntryPrice - TrailingStart2*MinPoint) // 第二級跟蹤止損的條件表達式//

  {

  If(High >= LowestAfterEntry[1] + TrailingStop2*MinPoint)

  {

  MyExitPrice = LowestAfterEntry[1] + TrailingStop2*MinPoint;

  BuyToCover(0,MyExitPrice);

  }

  }else if(LowestAfterEntry[1] <= MyEntryPrice - TrailingStart1*MinPoint)// 第一級跟蹤止損的條件表達式//

  {

  If(High >= LowestAfterEntry[1] + TrailingStop1*MinPoint)

  {

  MyExitPrice = LowestAfterEntry[1] + TrailingStop1*MinPoint;

  BuyToCover(0,MyExitPrice);

  }

  }else If(High >= MyEntryPrice + StopLossSet*MinPoint)//可以在這里寫上初始的止損處理//

  {

  MyExitPrice = MyEntryPrice + StopLossSet*MinPoint;

  BuyToCover(0,MyExitPrice);

  }

  }

  End

  看吧,改了一下條件,這系統(tǒng)就變得不錯的,所以說ADX指標是不錯的,我的很多趨勢操作也是借鑒這個指標的。當然,我這個代碼也是有缺陷的,就是買賣的時候,觸發(fā)止盈之后,條件符合,持續(xù)開倉,所以造成很大的浪費手續(xù)費,但怎么改進,我現(xiàn)在也懶得去寫了,有興趣的朋友可以自己弄了。

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容