2018年6月15日 星期五

開發商品的交易系統 - 進階篇 [13]

EasyTrader ArtNo 299
在前面幾篇介紹了投資組合(PortFolio Trader)運作的基本邏輯觀念與相關程式語法的說明,接下來我們就利用一個範例策略來做說明

動量指標又叫MTM指標,其英文全稱是“Momentom Index”,是一種專門研究股價波動的中短期技術分析工具。 動量指數以分析股價波動的速度為目的,研究股價在波動過程中各種加速,減速,慣性作用以及股價由靜到動或由動轉靜的現象。動量指數的理論基礎是價格和供需量的關係。

策略的邏輯是計算動量指標百分比來評估投資組合內所有商品,透過資金管理訊號來作指標排序,並依據排序的優先順序來決定投組內那些商品要做多,或那些商品要作空。策略內也加上了簡單的交易口數計算與出場方式
Portfolio_Rotation Signal 交易策略內容與說明
(這個策略是加在投組的訊號策略內)


//動量指標百分比做為投組每個商品每根K棒的計算評估基準
inputs:Formula(PercentChange(close, 14));
variables: formulaValue(0);

formulaValue = Formula;

//判斷交易策略是否在投組交易APP內執行
if getappinfo(aiisportfoliomode) <> 1 then
raiseruntimeerror("Signal can be used in Portfolio only.");

//將動量指標百分比數值formulaValue 存在變數RotationalValue 內
pmm_set_my_named_num("RotationalValue", formulaValue);

//建立作多/作空進場訊號
buy("LE") next bar at Highest(Close,5) stop ;
sellshort("SE") next bar at Lowest(Close,5) stop ;

//將各商品的部位狀態以 pmm_set_my_status 關鍵詞存放
pmm_set_my_status(iffstring(marketposition = 0, "Flat",iffstring(marketposition = 1, "Long", "Short")));

// 資金分配
var: PotentialEntryPrice(close), MoneyCostForInvestPerCtrct(0);

if (entryprice > 0) then PotentialEntryPrice = entryprice;

//計算每筆交易成本 = 保證金+最大潛在損失(這部分可以在投資組合設定畫面內輸入)
MoneyCostForInvestPerCtrct =
pmms_calc_money_cost_for_entry_per_cntrct(PotentialEntryPrice, Portfolio_GetMarginPerContract)+
pmms_calc_money_cost_for_entry_per_cntrct(PotentialEntryPrice, Portfolio_GetMaxPotentialLossPerContract);

//如果交易成本小於0則輸出錯誤信息
if 0 > MoneyCostForInvestPerCtrct then
raiseruntimeerror( text("Error! Price = ", PotentialEntryPrice:0:6, ", PMargin = ", Portfolio_GetMarginPerContract, ", PMaxPLoss = ", Portfolio_GetMaxPotentialLossPerContract));


// 將商品貨幣轉換成投組貨幣並存入變數 MoneyCostForInvestPerCtrct
pmm_set_my_named_num("MoneyCostForInvestPerCtrct", pmms_to_portfolio_currency(MoneyCostForInvestPerCtrct));

// 出場條件
inputs: StopLossPcntsOfPortfolio(0.1), ProfitTargetPcntsOfPortfolio(0.1);
variable: value(0);

setstopposition;

//以投組總權益的千分之一做為停損/停利的基準(會先將貨幣匯率作轉換)
value = StopLossPcntsOfPortfolio * 0.01 * Portfolio_Equity;
setstoploss(convert_currency(datetime[0], portfolio_CurrencyCode, SymbolCurrencyCode, value));

value = ProfitTargetPcntsOfPortfolio * 0.01 * Portfolio_Equity;
setprofittarget(convert_currency(datetime[0], portfolio_CurrencyCode, SymbolCurrencyCode, value));


Portfolio_Rotation_MM Signal資金管理訊號內容與說明(管理並決定進場交易的商品)
(這個策略是加在投資組合設定的資金管理訊號內)


//清除 PowerEditor 內 Debug輸出視窗內的信息
once cleardebug;

//允許作多及作空的商品數量
inputs:BuyBestX(3),SellWorstY(3);

//是否輸出 Log信息
Input: use_logging(false);
variables: idx(0), strategyIdx(0), strategyValue(0);

//宣告儲存商品索引碼與動量變動百分比數值的二維陣列並賦予初值-1
arrays: allStrategies[10000, 1](-1);

//判斷資金管理訊號是否在投組交易APP內執行
if getappinfo(aiisportfoliomode) <> 1 then
raiseruntimeerror("Signal can be applied (as Money Management Signal) in Portfolio only.");

//若輸入參數 BuyBestX + SellWorstY 大於參與交易商品的總數量pmms_strategies_count則輸出錯誤信息
if pmms_strategies_count < BuyBestX + SellWorstY then
raiseruntimeerror(text("Portfolio has not enough instruments: instruments number = ", pmms_strategies_count, "; BuyBestX = ", BuyBestX, "; SellWorstY = ", SellWorstY));


//停止所有策略進場建立部位
pmms_strategies_deny_entries_all;

//將所有商品索引碼及動量變動百分比數值存入陣列
for strategyIdx = 0 to pmms_strategies_count - 1 begin

strategyValue = pmms_get_strategy_named_num(strategyIdx, "RotationalValue");
allStrategies[strategyIdx , 0] = strategyValue;
allStrategies[strategyIdx , 1] = strategyIdx;

end;


//將陣列作遞減排序
Sort2DArrayByKey(allStrategies, pmms_strategies_count, 1);

//宣告變數與兩個動態陣列
variables: inLong(0), inShort(0);
arrays: strategiesLong[](-1), strategiesShort[](-1);

//將作多未平倉的商品數量存入變數 inLong (陣列內存的是作多未平倉商品的索引碼)
inLong = pmms_strategies_in_long_count(strategiesLong);

//將作空未平倉的商品數量存入變數 inShort (陣列內存的是作空未平倉商品的索引碼)
inShort = pmms_strategies_in_short_count(strategiesShort);

//輸出作多/作空的商品數量
if use_logging then
print( "strategies in position: long=",inLong, ", short=", inShort );

var : cur_idx(0);

//選擇動量變動百分比前 N名的商品索引碼
for idx = 0 to BuyBestX - 1 begin

//取得商品索引碼
cur_idx = allStrategies[idx, 1];

//如果該商品索引碼不在作多未平倉的陣列內,允許該商品建立多單部位,否則將該商品位置以-1填入
if (not array_contains(strategiesLong, cur_idx)) then
pmms_strategy_allow_long_entries(cur_idx)
else
strategiesLong[array_indexof(strategiesLong, cur_idx)] = -1;

//輸出作多的商品名稱
if use_logging then
print( "strategy ", pmms_strategy_symbol(cur_idx), "long entry" );

//如果有口數分配需求,則依資金分配計算交易口數
if UsePortfolioMoneyPcnt then
pmms_strategy_set_entry_contracts(
cur_idx,
pmms_calc_contracts_for_entry( PortfolioMoneyPcntForEntry, cur_idx )
);
end;

//選擇動量變動百分比後N名的商品索引碼
for idx = pmms_strategies_count - 1 downto pmms_strategies_count - SellWorstY begin

//取得商品索引碼
cur_idx = allStrategies[idx, 1];

//如果該商品索引碼不在作空未平倉的陣列內,允許該商品建立空單部位,否則將該商品位置以-1填入
if (not array_contains(strategiesShort, cur_idx)) then
pmms_strategy_allow_short_entries(cur_idx)
else
strategiesShort[array_indexof(strategiesShort, cur_idx)] = -1;

//輸出作空的商品名稱
if use_logging then
print( "strategy ", pmms_strategy_symbol(cur_idx), "short entry" );

//如果有口數分配需求,則依資金分配計算交易口數
if UsePortfolioMoneyPcnt then
pmms_strategy_set_entry_contracts(
cur_idx,
pmms_calc_contracts_for_entry( PortfolioMoneyPcntForEntry, cur_idx )
);
end;

// 強迫多單部位平倉(如果多單陣列內的商品索引碼不是-1,則將該商品平倉)
for idx = 0 to inLong - 1 begin
value1 = strategiesLong[idx];
if value1 >= 0 then begin
pmms_strategy_close_position(value1);

//輸出被平倉的商品名稱
if use_logging then
print( "strategy ", pmms_strategy_symbol(value1), "force position close" );
end;
end;

// 強迫空單部位平倉(如果空單陣列內的商品索引碼不是-1,則將該商品平倉)
for idx = 0 to inShort - 1 begin
value1 = strategiesShort[idx];
if value1 >= 0 then begin
pmms_strategy_close_position(value1);

//輸出被平倉的商品名稱
if use_logging then
print( "strategy ", pmms_strategy_symbol(value1), "force position close" );
end;
end;

// 決定是否做口數分配與可分配資金
inputs:
UsePortfolioMoneyPcnt(False),
PortfolioMoneyPcntForEntry(1);

if use_logging then

print("------------------------------------------------------------------")

為了方便測試,我將不同的商品指數都以日K方式匯入20010101~20180531資料,在QM裡的設定都比照台指期,並放入投資組合內,主策略訊號檔為上文中的 Portfolio_Rotation, 而資金管理訊號檔為 Portfolio_Rotation_MM



針對12個商品只選出指標排名前6個作多單進場(不作空單)的績效表現


針對12個商品只選出指標排名後6個作空單進場(不作多單)的績效表現




針對12個商品只選出指標排名前3個作多單進場後3個作空單進場的績效表現




透過特定的指標值或是個人熟悉的評價方式來篩選交易的商品以及多空方向,能讓我們的策略組合更具有彈性變化,有興趣的讀者可以參照文中的方式自行做變化運用

資料參考來源 https://www.multicharts.com

6 則留言: