原理
■ 已經上桌的成果
BefDays的設計
幾天前的一年最高價?這觀念有點難接受。你只要想,如果今天創最高價,那一年最高價當然不是今天、明天、後天...的創高價,而是以前的某一天。
一般的創新高寫法如下:
|
v_highest = highest(close,240); //計算240天收盤最高價 if (close = v_highest) then Ret=1; // 如果今天收盤是最高價就是創新高 |
這有什麼問題?
(1)本來的一年最高價應該是在幾個月前,結果變成了今天。
(2)事實上突破一年最高價在25%以內我們都還是可以進場(見_1的第二階段趨勢樣板7.目前股價距離五十二週高點不超過25%)但上述寫法你根本不曉得一年最高價在哪裡?又如何知道何謂25%以內?因為今天的創高價已經變成一年最高價了。
所以我們必須抓幾天前(BefDays)的最高價,我將它設為60天,因為最高價發生的日期,我們希望它至少離今天有60天(整理時間夠長)。這數字並無一定要求,純為自由心證。
加入這個設計,我們就能準確地知道「真正的一年最高點」在哪裡,不是今天、明天創新高的最高價,這樣我們就可以限定只有收盤價距離一年最高價-10%(perMinHigh)到+25%(perMaxHigh)的範圍內才會符合選股條件,這樣可以大幅減少選股結果數目。於是抓創一年新高的程式碼變成如下:
|
var: v_highest(0); //一年最高點 var: v_diff_high(0); //收盤距一年高點距離 -10%~+10% input:perMinHIGH(-10); setinputname(1,"距最高點距離(最少)"); //-10% input:perMaxHIGH(25); setinputname(2,"距最高點距離(最多)"); //目前股價距離五十二週高點不超過25%(愈接近愈好) input:BefDays(60); SetInputName(5,"幾天前的最高價"); v_highest= highest(high[BefDays], dayRange); //如60天以前的一年新高。 v_diff_high = round((close - v_highest) / v_highest * 100,1); if not (v_diff_high >= perMinHIGH and v_diff_high <= perMaxHIGH) then return; |
請看下面一張圖,一旦股價創新高,那新高在哪裡?如果沒有BefDays的設計,那麼你的買點就只有2014/01/10創新高那一天,之後你的程式就抓不到了,因為現在它的新高已經移到2014/1/10。
BefDays如為60天,意指我要抓取60天以前的一年新高,因此如下圖創新高後拉回的買點1~買點5,因為高點還是在2013/7/29日,在超過高點的3%或5%之內都是買點。
XS腳本
|
{ 名稱:XS超績創高 } var: v_ma1(0), v_ma2(0), v_ma3(0); var: v_lowest(0); //一年最低點 var: v_highest(0); //一年最高點 var: v_avg_vol(0); //VolLength 天數的平均成交量 var: v_diff_low(0); //距離一年最低點距離 var: v_diff_high(0); //收盤距一年高點距離 -10%~+10% var: v_QGrowth(0); // 季稅後淨利成長率 input:perMinHIGH(-10); setinputname(1,"距最高點距離(最少)"); //-10% input:perMaxHIGH(25); setinputname(2,"距最高點距離(最多)"); //目前股價距離五十二週高點不超過25%(愈接近愈好) input:paraGrowth1(-100); setinputname(3,"連續三季至少YOY獲利成長"); //20%,-100%指不考慮,單季稅後淨利YOY成長率 input:paraGrowth2(-100); setinputname(4,"最近一季轉機股成長率"); //100%,-100%指不考慮,單季稅後淨利YOY成長率 input:dayRange(240); setinputname(5,"創幾日新高"); input:BefDays(60); SetInputName(6,"幾天前的最高價"); input:perMinLow(30); setinputname(7,"距最低點漲幅(最少)"); //超績30,大漲60 input:perMaxLow(300); setinputname(8,"距最低點漲幅(最多)"); //300 input:VolLength(10); SetInputName(9, "均量天期"); input:VolumeLimit(500); SetInputName(10, "最小均量"); input:Leng1(50); SetInputName(11,"MA50"); input:Leng2(150); SetInputName(12,"MA150"); input:Leng3(200); SetInputName(13,"MA200"); settotalbar(3); // 過濾掉成交量太低的 v_avg_vol = Average(volume, VolLength); if v_avg_vol < VolumeLimit then return; // 判斷 股價>50ma>150ma>200ma v_ma1 = average(close, Leng1); v_ma2 = average(close, Leng2); v_ma3 = average(close, Leng3); condition1 = close > v_ma1; condition2 = v_ma1 > v_ma2; condition3 = v_ma2 > v_ma3; if not (condition1 and condition2 and condition3) then return; //股價>一年低點30~300% v_lowest = lowest(low, dayRange); v_diff_low = round((close - v_lowest) / v_lowest * 100,1); if not (v_diff_low >= perMinLow and v_diff_low <= perMaxLow) then return; // *** 判斷最高價 *** //舊寫法,一創新高就變最高價 v_highest = highest(close,day); v_highest= highest(high[BefDays], dayRange); //如60天以前的一年新高。 v_diff_high = round((close - v_highest) / v_highest * 100,1); if not (v_diff_high >= perMinHIGH and v_diff_high <= perMaxHIGH) then return; // 判斷 200ma已經上揚一個月 if not trueall(v_ma3 >= v_ma3[1], 20) then return; //*** 基本面 *** //v_QGrowth = GetField("稅後淨利成長率","Q"); value1 = GetField("稅後淨利成長率","Q"); value2 = GetField("稅後淨利成長率","Q")[1]; value3 = GetField("稅後淨利成長率","Q")[2]; if not ((value1 >= paraGrowth1 and value2 >= paraGrowth1 and value3 >= paraGrowth1) or (value1 >= paraGrowth2)) then return; SetOutputName1("最低點"); OutputField1(v_lowest); SetOutputName2("距最低點"); OutputField2(" "+NumToStr(v_diff_low,1)+"%"); SetOutputName3("最高點"); OutputField3(v_highest); SetOutputName4("距最高點"); OutputField4(v_diff_high); SetOutputName5("成交均量");OutputField5(v_avg_vol); SetOutputName6("成長率1");OutputField6(value1); SetOutputName7("成長率2");OutputField7(value2); SetOutputName8("成長率3");OutputField8(value3); Ret = 1; |
