Author Archives: 發財橘子

高現金股利低本益比且本業仍不差

網友想要挑一些急跌後可以留意的股票,我設了三個條件: 高現金股利,低本益比,本益穩定

寫了一個選股腳本如下:

input:peratio(17,"本益比上限倍數");
input:ratio(60,"現金股利佔股利之比重下限");
input:epsl(2,"預估本業EPS下限");
input:rate1(5,"累計營收成長率下限");
 
value1=GetField("累計營收年增率","M");//單位%
value2=GetField("現金股利佔股利比重","Y");
value3=GetField("營業利益","Q");//單位百萬;
value4=GetField("最新股本");//單位億;
value5=summation(value3,4)/(value4*10);//每股預估EPS

if
value1>rate1//本業持續成長
and 
value2>ratio//主要以現金股利為主
and
value5>EPSl//每股推估本業獲利高
and 
close/value5<peratio//本益比低
then ret=1;

 

我用比較嚴格的條件

1。本益比低於十

2。現金股利佔八成以上

3。預估eps大於五

4。累計營收成長率超過兩位數

 

挑出來的股票如下:

050902

 

 

 

xqlite banner

 

sector trade(類股輪動操作法)初體驗

類股輪動操作法的邏輯很簡單,找到現在表現最強的產業,投資其龍頭股。以前這種操作很難把它自動化,更別說去回溯測試這個策略的勝率及績效了,我試著把它程式化,算是拋磚引玉,希望各位可以發展出更強大的類股輪動操作策略。

 

我的演算過程分成兩部份,一部份是找出走勢比加權指數強的產業指數,另一部份則是找出各細產業中股價最活潑的個股

在第一部份,我的作法還是計算各產業指數與大盤相除後的BB值,這個值突破BB值上限就是表現異常強勢,以塑化原料為例就像下面這張圖

050601

 

第二部份的作法則是先找出貝他最高的股票

我訂了兩個條件

1.貝他值大於1

2.月成交量平均大於5000張

結果選出了433檔股票。

接下來我就開始把這433檔股票,拿去跑下面我寫的這個腳本

這個腳本的概念就是先把這433檔的相關細產業指數拿去跟大盤比強度,強度異常時,就觸發該產業在這433檔中所屬的股票。

我從這433檔股票中,挑出18檔股票,這些股票分別是其所屬產業中的龍頭股,然後請了公司的高手高手高高手寫了以下的指標

input: Length(20); SetInputName(1, "布林通道天數");
input: BandRange(2);SetInputName(2, "上下寬度");
input: MALength(10);SetInputName(3, "MA天期");
array:
ValueArray[18](0),
ratioarray[18](0),
uparray[18](0),
dnarray[18](0);
var:x(0);
var:si(0);// 商品所在的產業
if symbol="1101.TW" then si=1;
if symbol="1305.TW" then si=2;
if symbol="1452.TW" then si=3;
if symbol="1536.TW" then si=4;
if symbol="1460.TW" then si=5;
if symbol="1476.TW" then si=6;
if symbol="6269.TW" then si=7;
if symbol="2031.TW" then si=8;
if symbol="2014.TW" then si=9;
if symbol="2393.TW" then si=10;
if symbol="2615.TW" then si=11;
if symbol="2409.TW" then si=12;
if symbol="2882.TW" then si=13;
if symbol="6005.TW" then si=14;
if symbol="2606.TW" then si=15;
if symbol="3044.TW" then si=16;
if symbol="6244.TW" then si=17;
if symbol="9914.TW" then si=18;
if si = 0 then return;
valuearray[1]=GetSymbolField("I011010.TW","收盤價");//水泥
valuearray[2]=GetSymbolField("I013010.TW","收盤價");//塑化原料
valuearray[3]=GetSymbolField("I014010.TW","收盤價");//加工絲
valuearray[4]=GetSymbolField("I022020.TW","收盤價");//汽車零組件
valuearray[5]=GetSymbolField("I014040.TW","收盤價");//織布
valuearray[6]=GetSymbolField("I014030.TW","收盤價");//成衣
valuearray[7]=GetSymbolField("I023320.TW","收盤價");//軟板
valuearray[8]=GetSymbolField("I020010.TW","收盤價");//不銹鋼
valuearray[9]=GetSymbolField("I020020.TW","收盤價");//平板鋼
valuearray[10]=GetSymbolField("I023060.TW","收盤價");//LED
valuearray[11]=GetSymbolField("I026020.TW","收盤價");//貨櫃航運
valuearray[12]=GetSymbolField("I023080.TW","收盤價");//面板
valuearray[13]=GetSymbolField("I028010.TW","收盤價");//金控
valuearray[14]=GetSymbolField("I028030.TW","收盤價");//證券
valuearray[15]=GetSymbolField("I026030.TW","收盤價");//散裝航運
valuearray[16]=GetSymbolField("I023230.TW","收盤價");//印刷電路板
valuearray[17]=GetSymbolField("I023130.TW","收盤價");//太陽能
valuearray[18]=GetSymbolField("I099040.TW","收盤價");//自行車

value1=GetSymbolField("TSE.TW","收盤價");
ratioarray[si]=valuearray[si]/value1;
uparray[si]=bollingerband(ratioarray[si],length,bandrange);
dnarray[si]=bollingerband(ratioarray[si],length,-1*bandrange);
plot1(uparray[si], "UB");
plot2(dnarray[si], "DB");
plot3(ratioarray[si], "Ratio");
if ratioarray[si] cross over uparray[si] then
plot4(1, "穿越")
else
noplot(4);

這個指標如果畫成圖就像下圖

050602

 

這個腳本把plot4改成ret=1就成了警示腳本

下圖就是過去三年的回測報告

050603

 

績效還真的不錯。

透過這個腳本,未來這十八檔股票所屬的細產業如果比大盤表現異常突出,系統會針對該檔股票觸發信號

 

以上就是所謂sector trade的一種基本類型,希望可以激發大家更多的靈感

 

xqlite banner

由市場老手的交易秘訣所衍生出來的交易策略(一)

這陣子盤這麼差,只作多不作空的人日子難過,想起一位多空都作的老業內,他的作法是多頭時挑剛開始冒出來比大盤強的作多,空頭時挑剛開始比大盤弱的作空,我把這樣的思維寫成交易策略,回測的結果不差,提供給大家,以此為基礎,進一步優化成更佳的交易策略。

我的思維如下

1.把加權指數五日MA在20日MA均線之上視為多頭,反之則是空頭。

2.我把股價當分子,加權指數當分母,然後拿這個值去算BBand,一旦這個值突破BBand的上沿,代表這檔股票跟大盤的相對強度已經出現跟以往正常的區間不同。

3.這檔股票短線沒有急漲的太過頭

符合以上三個條件的腳本寫法如下:

value1=GetSymbolField("TSE.TW","收盤價")/close;
if value1<>0
then value1=1/value1;

input: Length(20); SetInputName(1, "布林通道天數");
input: BandRange(2);SetInputName(2, "上下寬度");

variable: up(0), down(0), mid(0);

up = bollingerband(value1, Length, BandRange);

if value1 cross over up 
and average(GetSymbolField("TSE.TW","收盤價"),5)>
average(GetSymbolField("TSE.TW","收盤價"),20)
and close<close[2]*1.07
then ret=1;

我拿這個腳本來跑今年以來有量的中小型股,回測報告如下 050501 這個策略的核心精神就是大盤多頭時找比大盤還強的作多,大盤空頭時找比大盤還弱的作空,我們以楠梓電這檔個股為例,請看下圖 050502 從這張圖也可以看到,當BBand上下兩條線縮的很近時一旦數值突破上限或下限時,訊號的可信度更高 xqlite banner

多空交易(long-short trading)

在金融情勢詭譎多變的時候,我們很難判斷接下來的股市會怎麼走,但如果我們很清楚知道,在同一行業裡的某A股票,基本面長期表現會比某B股票好,這時候我們就可以作多A股票,放空B股票,不管大盤漲還跌,都可以靠這樣的操作賺到錢,這樣的操作就稱之為多空交易(long-short trading)

舉個例子,大家都知道台積電跟聯電長期以來競爭力差很大,但以往聯電的股性有時候會突然活潑了起來,短期不見得表現比台積電差,這時候我們可以把兩家公司的總市值相除,然後再取兩個長短天期不同的移動平均線,這樣我們就可以觀察兩家公司總市值的長期趨勢變化,也可以透過長短天期移動平均線的黃金交叉及死亡交叉,來決定多空交易的進場點及平倉時點。

根據上述的精神,我寫了一個畫圖的腳本如下:

input:period1(4,"短期別");
input:period2(12,"長期別");
setbackbar(12);
settotalbar(600);
value1=GetSymbolField("2303.tw","總市值");
value2=GetField("總市值");
value3=value1/value2;
value4=average(value3,period1);
value5=average(value3,period2);
plot1(value4);
plot2(value5);

使用這個腳本,用週線的頻率,可以畫出下面這張圖

050402從這張圖,我們就可以很清楚的看到如果我們在2014年八月四日那一週開始作多台積電,放空聯電,到目前為止,都還沒有出現平倉的訊號,而到目前為止的投資報酬率是三成左右,如果我們用個股期貨來操作,報酬率就會因為槓桿而變得很驚人。

我想大家一定會說我在看圖說故事,台積電與聯電的例子大家都太瞭解了,應該要提供一些新的多空交易標的。

在這個部落格,我一貫不報明牌,但我很喜歡分享我的交易經驗及思考的方式,所以,我提出幾個多空交易的配對思考方向,供大家作參考

方向一: 尋找因為某事件或議題,造成一個長期趨勢,這時就可以把因此趨勢而會受益與受害的公司作配對

這個例子最明顯的就是統一跟味全

050403

另外像是台幣升值時,作多食品股,作空外銷電子股

方向二,當某原料長期上漲時,作多生產該原物料的上游,作空下游,相反的,某原料價格長期下跌時,作多下游,作空上游,不過必須留意的是下游是否有高價庫存待消化,如果有,那轉折點會在原料下跌趨勢一段時間之後

方向三,同一產業競爭力有明顯差異的兩家公司,前面提到的台積電與聯電是一個明顯的例子,以前友達跟華映也是很好的多空交易標的,台郡跟嘉聯益是另一個明顯的例子

050404

方向四  爭奪特定有限市場(如國內市場)而明顯分出勝負時

這種最有名的就是國泰金與新光金

050405

 

 

隨著個股期貨以及借券等措施的開放,也隨著XS即將支援跨商品功能,我們愈來愈有機會透過XS尋找及實踐各種不同類型的多空交易。如此一來,我們可以專心研究同產業或特定議題趨勢下的受益與受害公司,並且透過一多一空的方式,進行多空交易,如此一來,我們就不必理會國際金融市場對於台股的多空衝擊,只要專注在企業競爭力的研究上。

 

 

 

xqlite banner

 

 

報復性反彈

股票市場情緒很極端,漲的時候眾星拱月,跌的時候棄如敝屣,超漲超跌時有所見,超跌的股票,往往像是過街老鼠,人人喊打,但真的跌的太過頭了,也會有報復性上漲的一天,今天我們就來探討,像這樣的公司,要透過什麼策略程式,才能提早發現。

報復性上漲的例子很多,這幾年,最有名的例子大約有下面幾個

050302 050301

這些股票的特徵如下:

1.從還原月線看,股價都連續跌了好幾個月

2.從日線看,在報復性反彈時,成交量佔大盤的比重回昇,股價比大盤強且都有出現至少一根的長紅棒

根據這兩個特徵,我使用XS即將上線的跨頻率語法,寫了一個用月線RSI找超跌,用日線找短線轉強的股票,腳本如下:

//先來找出月線RSI小於5的股票
input:period(6,"RSI期別");
var:x(0),up(0),down(0);
up=0;
down=0;
for x=0 to period-1
begin
if GetField("收盤價","AM")[x]>GetField("收盤價","AM")[x+1]
//取得還原月線的收盤價 並計算RSI
then
up=up+GetField("收盤價","AM")[x]-GetField("收盤價","AM")[x+1]
else
down=down+GetField("收盤價","AM")[x+1]-GetField("收盤價","AM")[x];
end;
value1=up/(up+down)*100;

value2=GetField("資金流向");
value3=GetField("強弱指標","D");

if value1<=25
then begin
if countif(value3>0,5)>=4
or countif(value2-value2[1]>0,5)>=3
or countif(close>=close[1]*1.04,3)>=1
then ret=1;
end;

之所以月線要這麼不厭其煩的用Getfield的方式來模擬RSI,主要是因為跨頻率如果以是日線為計算基準時,若直接套用RSI的期別時,電腦計算期別時是以日線為準,這時候,每天的月RSI其實是同樣的數字,這樣算出來的結果,就不是我們想要的了。

今早用這個腳本跑出來的股票有潤泰全,三商壽這兩檔,由於這個腳本對於日線轉強的標準訂的比較低,後續還是要搭配日線其他指標及籌碼來觀察是否真的轉強

 

 

 

 

撰寫交易策略的SOP

隨著開始使用XS寫交易策略的朋友們愈來愈多,我們愈來愈常被求救,問題看多了,歸納整理後,我寫了一個撰寫交易策略的SOP,我認為在撰寫交易腳本時,有四大步驟,嚴謹且按步就班地作好每個步驟,應該可以協助我們完成交易策略的撰寫。

這四個步驟如下圖

撰寫腳本的SOP

 

茲分項說明之

一,準備數據

程式交易語法跟其他如C++,Java等不同之處,是在於它的目標很明確~透過大量金融數據的運算,作成交易決策,所以在一個程式交易腳本中,最基本的課題是: “要拿那些金融數據進來運算?”

每個腳本,都像一道食譜,每個食譜,都會要我們先準備食材,腳本的食材,就是我們要拿下去運算的每個元素,在XS的腳本中,這些要拿來加減乘除作運算的元素,可以歸類為以下幾種

1. 即時行情的數據。包括單量,當日漲幅,內盤量,外盤量,五檔委買賣的價與委託量等等,我們可以用 Getquote的語法把它們拉出來使用。

2. 盤後數據。包括法人進出,資券變化,主力進出等等數據,我們用Getfield的語法把這些欄位拿到腳本中來使用

3. 回傳值。開高低收成交量等語法中最基本的元素,在以K棒為基礎的架構裡,我們可以用Close[n]之類的語法,把K棒中 的每一個被存下來的值拿來運算。

4. 參數。為了更改參數方便而由使用者以INPUT的語法所設定的參數,也是可以被拿來腳本中作運算。

5. 變數。為了運算方便,由使用者自行宣告的變數,也是腳本中常見的元素。

6. 常數。有的時候,就是會運用到簡單的阿拉伯數字,或是True及false這兩個布林值,這些都是腳本運算中常用的元素。當我們要要撰寫一個腳本時,就像食譜要先準備的食材一樣,我們得先決定要用上述六大類裡的那些元素,這個決定的工作,就像是煮一道菜之前,先把相關的食材從冰箱裡取出來。

0 42201 

決定好之後,接下來要做的是事情有兩個

第一個是宣告: 我們先透過宣告的方式,把要用的變數及參數先準備好,我們為它們取名字,設初始值。

第二個是指定: 然後接下來我們用getquote及getfield的語法,把盤後資料及盤中資料指定到特定的某個變數

二,建構演算

以上的這兩個步驟,就好像是煮菜之前的備料工作。備完料,接下來就是建構演算的機制,在這當中,若是有需要,會使用到系統或自訂的 函數。    大家可以透過先前學會的流程控,以及各種函數,透過數學及邏輯運算,完成各種運算。

這部份主要是看個人的功力,只能多看多寫,多看別人寫過的好語法。

三,設定輸出條件

接下來,就是建立輸出條件,我們用if ……..then  ret=1; 來指定策略雷達的觸發條件,以及選股的符合條件,用if………then plot1…;來輸出自訂指標。

我與個例子來說明以上的流程

我們希望電腦在個股符合下列三個條件時通知我們,

  1.    十日法人買超的移動平均超過1000張
  2.    當日外盤量佔成交量超過五成
  3.    當日股價比前一日上漲

那麼我們可以寫下一個腳本如下:

各位可以看到,我們依以下的步驟在完成一個警示腳本

步驟一: 宣告參數

步驟二: 宣告變數

步驟三: 取得盤後資料

步驟四: 取得即時數據

步驟五: 建構運算關係

步驟六: 設立觸發,畫指標或確認 函數的敘述式

當然在實作上,步驟一到步驟五的任何一項 ,都可能因為沒有用到相關數據而被省略,最簡單的警示腳本如if close=high then ret=1;就只有步驟六而已。

但如果大家記得這六個基本的步驟,應該可以很快的把各式各樣的數據,同步放在一個警示腳本中來使用。

042202

 

 

 四,編譯與勘誤

接下來的編譯及勘誤,是另一個重點,很多朋友就算是提供了中文的勘誤,還是無法自行找出程式碼的問題之所在,所以我把大家常見的程式上的疏誤,以及在勘誤時系統會出現的訊息做了一個對照表如下,供大家參考。

XS的勘誤方式,跟其他的IDE類似,在使用者按下編譯按鈕之後,如果程式有Bug,會在訊息視窗中,以表格的方式來呈現錯誤的地方,其呈現方式如下:

 

物件名稱 行號 字元 錯誤描述
呈現腳本的名稱 顯示錯誤的敘述在第幾行 錯誤的地方是從該行的第幾個字元開始 表達錯誤的可能原因,俾使用者正確地找到錯誤。

 

根據我自己使用的經驗,User通常會出現的錯誤,以及XS編輯器對應會出現的勘誤訊息,大致有以下幾類。

 文字上的小失誤

 

錯誤描述 原因說明及備註
未知的關鍵字 “xxx”,請檢查是否有宣告此變數或是拼字是否有誤。 可能是自己宣告的參數或變數的名稱打字時打錯了,造成電腦無法理解這個字代表的意思
需要輸入更多參數。 通常是像plot1之類的忘了把裡頭的參數輸進去,如果是函數忘了輸入正確的參數個數,系統會直接呈現”需要輸入x個參數”
需要輸入 x ~ y 個參數。 輸入的參數比系統要求的多時會出現這個message
在 “xxxxxx” 之前可能少了”;”, “DOWNTO”, “TO”, “OR”, “XOR”, “AND”, “=”, “<>”, “<“, “>”, “<=”, “>=”, “Crosses Above”, “Crosses Over”, “Crosses Below”, “Crosses Under”, “+”, “-“, “*”, “/” 最有可能的是前一行忘了打分號。
編譯器看到了一個無法辨認的字 “x”,請檢查這個字有沒有寫錯。 這種情況通常是輸入了之前沒有宣告過的文字格式內容

 流程的錯誤

 

錯誤描述 原因說明及備註
for 迴圈的變數型態應為數值。 for的用法為for 某變數=xx to xxxxx及xxx必須都是數值
「IF/Once/While/Repeat」後面需要一個真偽值或是真偽值的判斷式。 這些流程的後面必須是一個布林值的判斷式,不能是一個結果是特定數值的運算式

 

 函數的錯誤使用

 

錯誤描述 原因說明及備註
需要輸入x個參數 這代表使用這函數所需要輸入的參數的個數與user實際輸入的參數並不相符,可能是漏打或是多打了某個參數。
函數 xxxxx:第 x 個參數應該是 Numeric(string)。 這代表使用者輸入的函數參數格式錯了,該是數字的地方使用了文字,或是該是文字的地方使用了數字。
函數宣告的輸入型態有誤,應該是 Numeric,NumericSimple,NumeircSeries, String,StringSimple,StringSeries,TrueFalse,TrueFalseSimple,TrueFalseSeries。 在自訂函數宣告參數時必須宣告資料的型態而不是直接使用初始值
函數 xxxxx:第 x 個參數應該是 Numeric 函數裡每一個參數的格式(type)必須是對的,不能把文字放到該填數值的函數去
參數的數值不可以在函數中被修改,如果有需修改參數值,請將參數型態改為 NumericRef(數值)或是 NumericArray(陣列)。 在函數中的參數,它的數值是不能在宣告後直接被賦予特定值的,例如不能寫input:abc(numeric);abc=1;

 

 用到不該用的欄位

 

錯誤描述 原因說明及備註
在「警示」腳本中無法使用「plot」 在警示類的腳本中不能使用plot
此欄位無法使用 [ ](無法索引前期值)。 例如在getquote的欄位裡使用前期值的語法
在「指標」腳本中無法使用「xxxxx」。 在指標類型的腳本中不能使用getquote的欄位

 

 數值與布林值使用上的混淆

 

錯誤描述 原因說明及備註
“=” 左右兩邊的型態不同。 數值是無法等於布林值的,例如不能寫value1=true; 因為value1是數值變數,true是布林值,應該要寫成condition1=true;
“+” 左右兩邊的型態不同。 數值跟布林值是無法相加的
“AND” 與左右兩邊的型態不同。 and的兩邊必須都是布林值的敘述,不能有數值
“-” 與右邊的型態不同 減號的兩邊都必須是數值
“not” 與右邊的型態不同。 not的兩邊都必須是布林值

 

 宣告參數時容易發生的失誤

 

錯誤描述 原因說明及備註
在指標跟警示裡面不用型態的方式,請修正。 在指標跟警示裡,使用input宣告參數時直接用初始值,而不是宣告資料型態。

 

 變數使用上的錯誤

 

錯誤描述 原因說明及備註
變數 “xxx” 為系統保留文字,請更改變數名稱。 宣告變數時用到了其他關鍵字, 或是重覆宣告了同名字的變數
變數 “xxx” 沒有宣告,請用 Vars: 的方式宣告,冒號後面是變數名稱再用括號填入預設值。例如: Vars:varA(100); 如果要宣告陣列請用 Arrays: 冒號後面是名稱再用 [] 設定維度與大小,括號填入預設值。例如 Arrays:arr1[10](0);。 直接使用了某個電腦看不懂的英文字詞,電腦會提醒把這個字詞宣告成變數後再來使用
xxxx不是陣列,不能在後面加 [ ],請把  [ ] 與裡面的數字移除掉。 在使用變數前一期值時要小心,不要直接指定特定一期值為某常數,因為這是陣列才會有的行為,例如可以寫value1=value1[1]+value1[2];但不能寫value1[1]=5;

 

 陣列使用上出現的疏誤

 

錯誤描述 原因說明及備註
變數宣告為 Array 但沒有宣告陣列維度,例:Array:arr[X](numericarray); 使用陣列時只記得宣告是陣列卻忘了宣告陣列的維度
有宣告陣列維度但變數並不是宣告為 Array。 宣告了陣列的參數,但忘了宣告陣列格式的變數,兩邊對不起來
陣列參照不正確。 宣告陣列後,必須按陣列的格式來assign值或變數,而不能像非陣列的assign方式,例如宣告了一個陣列如下:array:arr1[5](0);arr1[1]=1; 這樣寫是可以的,但不能寫成

arr1=1; 因為在陣列中的每一個變數都是獨立的,不能透過這種語法想要一次assign所有陣列的值都是1

同樣的,也不能寫成

value1=arr1;

因為左邊是一個變數,右邊是一個陣列。
另外維度兩邊對不起來時也可能出現陣列參照不正確的訊息

陣列(Array)宣告不支援超過9維的維度。 這種情況代表使用者宣告的陣列維度超過九個,這超出了系統所能提供的上限。

 

 

當編譯後出現錯誤訊息後,即可根據上面表格的說明,找出錯誤的原因並且加上修正,如此一來可以縮短程式開發的速度,並且讓程式可以忠實呈現使用者的想法。

 

 

 

xqlite banner

魚骨圖在投資決策上的實踐方式

魚骨圖又被稱為特性要因圖,是經理人們常用的工具,在要解決一個問題時,透過魚骨圖的方式,列出會影響結果的每個重要環節,然後透過腦力激盪,找出每個重要環節的核心要素。在進行投資決策時,魚骨圖也是一個蠻好用的工具,可以讓我們找出真正會影響股價波動的要素。

以下圖為例

魚骨圖範例

我每天都會把漲幅較大,且有一定成交量的股票,拿出來研究一翻,然後我歸納出這些股票常有的共同特徵

1.線型上在上昇趨勢中

2.籌碼是穩定的

3.今天開盤就明顯比較強

所以我就試著以魚骨圖的方式,列出要符合上述三個特徵,它們各別的要素是什麼,然後把這些要素寫成腳本

//先準備需要被拿來運算的資料
value1=GetField("法人買賣超張數");
value2=GetField("主力買賣超張數");
value3=GetField("融券增減張數");
value4=q_BoughtLotsAtOpen;//開盤委買張數
value5=q_SoldLotsAtOpen;//開盤委賣張數

//先宣告魚骨圖的魚骨數並先為false
condition1=false;
condition2=false;
condition3=false;
//描述魚骨在什麼情況下由false變成true
if value1[1]>0 and value2[1]>0 and value3[1]>0 
then condition1=true; //符合籌碼穩定的條件
//===============MACD =================================
input: FastLength(12,"DIF短期期數"), SlowLength(26,"DIF長期期數");
input: MACDLength(9,"MACD期數");
variable: difValue(0), macdValue(0), oscValue(0);
MACD(weightedclose(), FastLength, SlowLength, MACDLength, difValue, macdValue, oscValue);

if oscValue > 0 and average(close,5)>average(close,20)
then condition2=true; //符合上昇趨勢的條件

if open > close[1]*1.015 and value4>highest(value4[1],20) or value4-value5>200
then condition3=true; //符合開盤走強

if condition1 and condition2 and condition3
then ret=1;

這個腳本的結構,主要是用condition1………到conditionN來界定投資決策的重要環節,然後列出所有該環節底下的核心要素,並寫成條件式,然後再透過關係運算子and或是or來建構核心要素與該環節的成立要件,而投資決策的形成,必須是所有環節都成立。

在語法上,它的架構就如下圖

魚骨圖架構

在擬定交易策略時,針對當沖,隔日沖,短線,波段等不同的交易方式,會影響績效的環節不會一樣,每個環節裡的核心要素也不一樣,我的研究方法是把不同交易方式裡成功的例子拿出來研究,尋找真正會影響績效的環節,然後再透過各種嚐試及回測,找出最能代表每個環節表現的核心要素,然後透過上述的語法結構,完成一個投資決策的腳本。各位不妨試著以類似的方法完成自己的交易決策魚骨圖,然後根據上面的語法範例完成自己的投資決策腳本。

 

xqlite banner

 

檢查表在程式交易上的呈現方式

檢查表(check list)是一個被專業人士大量使用的工具,外科醫師用它來檢查手術前的準備工作,飛行員用它來完成起飛前的檢查,我試著把它的精神,透過語法,應用在投資操作上。檢查表是有機變動的,隨著投資經驗的累積,我們會更清楚地列出進場前要檢查的項目,這些項目,就是我們悠遊股海幾經風浪而不翻船的終極武器。

 

關於檢查表的概念及用法,天下出過一本書: 檢查表:不犯錯的秘密武器

042001

對檢查表的精神及實踐方法有興趣的朋友可以研究一下,我個人運用檢查表這個工具在投資上,已經有一段時間了,因為過往工作經驗的關係,我每天都會收到來自不同來源的明牌,有的是我以前的同事,有的是我以前認識的同業,有的是我收到的研究報告,甚至有些是我在網路社群裡收到的訊息,每次收到明牌,我都會先透過下方這個簡單的檢查表,檢查一遍,只有通過這樣檢查的股票,我才會列入觀察名單。

check list

這個檢查表其實並不複雜,其中的精神有幾點

1.股價不能太貴,我用PE及PB來衡量

2. 籌碼是良性而不是惡性,主要是看法人有沒有在賣以及籌碼是集中還是發散

3.技術面不能太醜。量能要溫和放大,均線多頭排列,這樣技術派的才會願意進來共襄盛舉

4.避開獲利了結賣壓。 所以短線漲幅不能太大

5.開始出現追價買盤。 最近一天要夠強。

 

根據這樣的想法,我把check list的精神,轉換成程式碼,由於check list的意義在於每一個項目都要符合,所以我很簡單地用and來串連每一個條件式,下面就是上述檢查表的對應程式碼

//先準備需要被拿來運算的資料
value1=GetField("法人買賣超張數","D");
value2=GetField("佔大盤成交量比","D");
value4=GetField("董監持股佔股本比例","D");
value5=GetField("外資持股比例","D");
value6=GetField("買家數","D");
value7=GetField("賣家數","D");
value8=GetField("股價淨值比","D");
value9=GetField("本益比","D");
//設計檢查表的規則
if average(value2,5)>average(value2,10)//成交量溫和放大
and average(value1,3)>0 //法人沒有站在賣方
and value4+value4>30 //籌碼集中
and average(value7,3)>average(value6,3)*1.03//籌碼是集中不是發散
and average(close,5) >average(close,10)//均線多頭排列
and close>close[1]*1.02//最近一天夠強
and close[5]< close*1.15//短期漲幅不算大
and value8<3//PB沒有太高
and value9<20//本益比不致於不合理

then ret=1;

 

在撰寫檢查表這類型的程式時,基本上有兩個步驟

1.先用getfield的語法,把檢查表要用到的資料欄位宣告成變數

2.透過if   …….and的語法,把所有條件式都串起來

如果條件式無法用一行敘述來完成,也可以用if ………..then condition1=true;這類的語法來表達一個較複查的條件

然後當這些條件式都是true時,這檔個股才會通過這個檢查表

以上述的腳本為例,用昨天的數據下去跑,完全符合上述條件的名單如下:

 

042002

 

 

 

 

 

以上是檢查表在程式交易上體現的方式,上述的例子只是個樣本,裡頭的參數也都可以調,使用的時候記得要用日線,資料讀取要超過十筆,各位也可以自行設計專屬的檢查表,就像天下那本書說的,這工具可以減少我們在投資上犯的錯。

 

xqlite banner

 

決策樹在程式交易上的應用

 

我每天都會把當天漲停的股票看一遍,觀察這些股票有沒有什麼樣的共同特徵? 後來我發現,這些股票當中,我比較買的下手的,基本上有一些同通點,於是,我試著用決策樹的思考流程,寫成一個策略腳本。

決策樹是專業經理人們,在作決策時,常用的工具,其目的在於找出要達到目標(股票漲停),所該選擇機率最高的決策路徑,在這個路徑上,有多個選擇的節點,在每個節點,必須作出對的選擇,才能最後得到最佳的方案。

舉個例子,大陸有個女生在決定是否與相親對象見面時,作了以下的決策樹

041902

這就是很典型的決策樹。

套用這樣的思考方式,我想要尋找的股票,我先畫出一個決策樹如下:

041901

我的思考如下:

1.我發現比較漲得兇的股本都不大,有個好消息,往往能貢獻較高EPS,所以我先設定最後我要的股票,股本要小於50億元。

2.要吸引市場追價,基本面要有一定的想像空間,所以我希望的基本面是最近一個月營收mom或yoy兩位數成長,或是毛利率成長。

3.我希望它的走勢

A.比大盤強

B.資金流入

4.我希望它在盤中

A.K棒中長紅

B.成交量超過千張

C.創盤中新高

根據上述的思考,我把它改寫成以下的腳本:

value1=q_CurrentCapitalin100Million;//股本:單位億元
value2=q_GrossMarginRate;//毛利率
value3=GetField("資金流向");
value4=GetField("強弱指標");
value5=GetField("投信買賣超");
value6=q_RevenueYoY;//營收年增率
value7=q_RevenueGrowth;//營收月增率
if value1<50//股本小於50億
then begin
if value6>9 //營收年增率兩位數成長
or value7>9//營收月增率兩位數成長
or value2>value2[1]//毛利率成長
then begin
if value4>0//比大盤強
and value3>average(value3,10)//資金淨入
then begin
if close>close[1]*1.02//K棒中長紅
then begin
if volume>1000//成交量大於1000張
then begin
if close=high//創盤中新高
then ret=1;
end;
end;
end;
end;
end;

 

在這個腳本裡,我用了大量的 if ……………then begin…………..end;

也用了and 跟or

透過這些關係運算子及流程控制元素,就可以完成一個決策樹。

各位不妨也試試自己先畫出一個決策樹,然後再根據上述的寫法,完成自己專屬的選股及交易策略

 

xqlite banner

 

Q指標

操作策略的形成,往往來自電光火石間,乍現的靈感,這些靈感,必須經過實證的研究,才能成為真正的交易策略,而自訂指標,就是實證研究的方法之一,經過研究,尋找及歸納出指標的應用方式,是交易策略的起點。

很多操作的策略,其成形的靈感,往往來自看盤的體驗上,例如我們總是想知道,現在是

1.上昇趨勢(up trend)

2.下降趨勢(down trend)

3.沒有趨勢( no trend)

那該如何判斷呢?

有人想到,如果把一定期間每天的漲跌累積起來,如果是上昇趨勢,這數字應該會是正的,如果是上降趨勢,這數字應該是負的,如果是盤勢,這數字應該是在零上下波動。

於是,就有人想出了一個叫作價格累積變化的指標(cumulative price change),我們簡稱為CPC

它的計算方式如下:

input:t1(10,"計算累積價格變動的bar數");
value1=close-close[1];//價格變化
value2=summation(value1,t1);//累積價格變化
plot1(value2,"累積價格變化");

這個指標跟加權指數的對照圖如下:

041801

 

當我們在自訂指標的時候,這種計算出一個時間序列,然後觀察這個時間序列與商品價格的對應關係,從而訂出交易策略,是一種最直覺的方法,但有的時候,這個指標的變動過於劇烈,有的時候這個指標的數字視商品價格而定,因為不大容易形成一個放諸各種商品皆適用的策略規則。

這時候我們最常運用的,就是長短天期移動平均線的方式,以上述的CPC指標為例,我們可以把上述的腳本改成以下的樣子

input:t1(10,"計算累積價格變動的bar數");
input:t2(5,"短期平均天期");
input:t3(10,"長期平均天期");
value1=close-close[1];//價格變化
value2=summation(value1,t1);//累積價格變化
value3=average(value2,t2);//短期平均
value4=average(value2,t3);//長期平均
plot1(value3,"短期累積價格變化平均");
plot2(value4,"長期累積價格變化平均");

這樣子的指標,對照大盤的圖如下:

041802

從上圖來看,我們大致可以發現,當短天期移動平均與長天期黃金交叉時,是個買進訊號,但如果是死亡交叉時,就是個賣出訊號。

很多大家耳熟能詳的指標所對應的交易訊號,基本上的概念都是用兩條不同天期的移動平均線去尋找黃金交叉或死亡交叉的點,以上面的腳本為例,如果我們要改寫成作多的交易策略,只要把plot1及plot2拿掉,改成以下的敘述即可

if value3 cross over value4 then ret=1;

兩條不同天期均線的對應關係,不是僅有那條線在那條線上面或下面而已,有的時候,兩條線的距離也很有意義。

這時候我們可以把 那條不同天期移動平均線相減,然後畫成柱狀線,這樣不僅可以看出那條線的高低比較,也可以看出那者間是愈拉愈近還是愈拉愈遠,基至連轉折點也可以一目了然。

例如上圖,我們只要再加下面這一行

plot3(value3-value4,"短期減長期");

下圖就是對應的圖

041803

對照上面的圖,有一個弱點,那就是我們用黃金交叉及死亡交叉來形成決策時,不是做多就是做空,那盤整的時候怎麼辦呢? 或者說,這類的交易策略在趨勢成形時可能極有效,但如果盤整時會不會就很容易出現一下子買進一下子賣出的錯誤訊號呢?

為了解決這個問題,很常被拿來使用的作法就是”去噪音” ,把盤整的因素考量進來,以這個CPC指標為例,如果我們認為CPC的移動平均線可以真正代表價格波動的趨勢,那麼每一個CPC的點到其移動平均線之間的距離,則是單一點偏離趨勢的值,這些偏離值的絕對值就是這個趨勢的噪音,噪音愈大,代表這個趨勢愈不明顯,噪音愈小,代表價格的波動主要是沿著趨勢在跑,這樣的趨勢代表性及持續性會較顯著。

所以我們可以試著算出噪音的移動平均線,然後再把CPC趨勢與噪音相除,如此就可以計算出考慮過噪音大小後的CPC的值,這個值就是所謂的Q指標

它的腳本如下:

input:t1(10,"計算累積價格變動的bar數");
input:t2(5,"計算價格累積變化量移動平均的期別");
input:t3(20,"計算雜訊的移動平均期別");

value1=close-close[1];//價格變化
value2=summation(value1,t1);//累積價格變化
value3=average(value2,t2);
value4=absvalue(value2-value3);//雜訊
value5=average(value4,t3);//把雜訊移動平均
variable:Qindicator(0);
if value5=0
then Qindicator=0
else
Qindicator=value3/value5*5;
plot1(Qindicator,"趨勢值");

這個Q指標與加權指數的對照圖如下:

041804

這個指標是過濾掉噪音後的趨勢

根據它的計算原理,我們可以訂出明確的交易訊號如下:

1.  -1到1: No trend

2.    1到2與-1到-2: Weak trending

3.    2到5與-2到-5: Moderate trending

4.    大於5與小於-5: Strong trending,當數值遠遠超過此數值,表示超買與超賣

 

從 Q指標這個例子,我們可以學習到,自訂指標的設計及移動平均線的計算,長短天期平均線的差值,以及去除噪音的方式,這些技巧學會後,可以讓我們把自訂指標的應用,做的更得心應用。

 

 

 

xqlite banner