程式交易教學 - VEXI Lab https://www.vexifx.com/bvi-ft/lab-education/ea_trading/ VEXI安達是一家全球領先的交易平台,提供全球外匯交易、指數交易、黃金交易、大宗商品交易等,還提供豐富的外匯、黃金等市場分析和學習資源,想了解更多VEXI就訪問中文官網或使用MT4交易平台。 Mon, 04 Sep 2023 01:08:11 +0000 zh-TW hourly 1 https://wordpress.org/?v=6.8.3 在早盤頭皮EA中加入馬丁格爾策略功能【複製源碼就可以使用】 https://www.vexifx.com/bvi-ft/lab-education/ea_trading/martingale/ Mon, 04 Sep 2023 01:04:33 +0000 https://www.vexifx.com/bvi-ft/lab-education/?post_type=ea_trading&p=35967 在早盤頭皮EA中加入馬丁格爾策略功能【複製源碼就可以使用】
上篇文章中介紹了在簡單的時間限制以及逆勢交易邏輯中,加入追蹤停損的話會有什麼影響。

本篇文章將介紹「追蹤停損」以外,如果加入「馬丁格爾策略」的話會有什麼樣的結果。

馬丁格爾策略主要是作為賭場策略而開發的。

策略非常簡單,就是把賭金一直加倍到盈利為止。

外匯交易中的馬丁格爾策略一般都是加2倍手數。

馬丁格爾策略的優點和缺點

以下為馬丁格爾策略的優點和缺點。

優點

優點是一次就可以賺回之前的全部虧損。

一般來說,一次虧損需要2次盈利才可以獲利,而馬丁格爾策略且只需要一次盈利就可以。

缺點

缺點就是,如果連續虧損的話資金馬上就會用完。

在外匯交易中,每筆交易都是獨立的,因此也有可能會出現連續虧損。

所以,在交易時需要充分的資金。

例如,初次下單是0.01手,連續虧損10次時,在第11次的手數就會變成10.24手。

馬丁格爾策略就是如果資金不夠就會馬上爆倉。

在外匯交易中需要對馬丁格爾的注意事項

馬丁格爾雖然有介紹說「一次就可以賺回全部虧損」,但這只限於與停損幅度與停利幅度相同時,如果停損幅度高於停利幅度的話一次不能賺回全部虧損。

在外匯交易中,根據點差以及下單時機等因素,並不只是按照加碼2倍來計算這麼簡單。

說明

首先介紹上次製作的EA。

・下單

時間在台灣時間清晨,並且RSI低於超賣線時下多單

時間在台灣時間清晨,並且RSI高於超買線時下空單

・平倉

根據停利價格和停損價格平倉

・其他

Copyright設置為「VEXI」

透過滑點和點差限制下單數量

設置為只能持有1個部位

可以修改Magic Number和手數

以上內容是上次製作的EA。

這次在以上內容中加入可以設置馬丁格爾次數的參數。

如果這個參數是「3」時,代表可以加碼3次,每次2倍手數。

如果連續虧損4次時,就不在加碼2倍,只按當時的價格下單。

製作EA

本程式是以上次的「製作早盤頭皮EA」為基礎製作,所以跳過上次內容,本篇文章至介紹加入的功能。

領域

input int MAGICMA = 23198721; // Magic Number
input double Lots =0.01; // 1手為10萬貨幣
input int Slippage = 4; // 限制下單滑點
input double MaxSpread = 5; // 限制下單點差
input double TakeProfit = 10.0; // 停利點數(pips)
input double LossCut = 20.0; // 停損點數(pips)
input int RSIPeriod=6; // 週期
input ENUM_APPLIED_PRICE RSIAppliedPrice = PRICE_CLOSE; // 價格來源
input int UpLine = 85; // 上線
input int DownLine = 25; // 下線
input int TradeTime = 0; // 交易時間

//設置馬丁格爾
input int NumMartin = 5; // 在馬丁格爾中加倍加碼的最大次數

在上次的參數中最後添加了NumMartin參數。

OnTick函數

void OnTick()
{
dSpread = (Ask - Bid) / (Point * 10);
int loseCount = 0; //虧損次數
for( int i= OrdersHistoryTotal()-1; i>=0; i-- ){ //①
if( OrderSelect(i, SELECT_BY_POS, MODE_HISTORY) == true && OrderMagicNumber() == MAGICMA && OrderSymbol() == Symbol() ){
if( OrderProfit() <= 0 ){ //②
if(loseCount >= NumMartin)break; //③
loseCount++; //②
}
else{
break;
}
}
}
double lot = Lots * MathPow(2, loseCount); //④
if(CalculateCurrentOrders()==0 && dSpread < MaxSpread) CheckForOpen(lot); //⑤
}
以上為OnTick函數。
    ①執行馬丁格爾時會根據最近交易的虧損次數來決定手數。
    因此,OnTick函數開始會先查看以往交易的虧損次數。

    ②根據 「OrderProfit() < =0」這個條件,如果盈虧小於0時,「loseCount」變量將會遞增加1。

    ③ loseCount的數值不能超過NumMartin參數的數值。

    ④ 根據loseCount的次數計算手數。
    MathPow只返回第1個參數的數值乘以第2個參數的數值。

    ⑤ 作為參數傳給CheckForOpen函數。

CheckForOpen函數

void CheckForOpen(double int lot)
{
int res;
double RSI = iRSI(Symbol(), 0, RSIPeriod, RSIAppliedPrice, 1);
if(TradeTime == TimeHour(Time[1]))
{
if(RSI < DownLine)
{
res=OrderSend(Symbol(), OP_BUY, lot, Ask, Slippage, Bid - TrailWidth * Point * 10, Ask + TakeProfit * Point * 10,"", MAGICMA, 0, Red);
}
if(RSI > UpLine)
{
res=OrderSend(Symbol(), OP_SELL, lot, Bid, Slippage, Ask + TrailWidth * Point * 10, Bid - TakeProfit * Point * 10, "", MAGICMA, 0, Blue);
}
}
}
這次手數會在OnTick函數中計算,因此可以將手數指定為函數。

不要忘記在OrderSend函數的第3個參數中指定接受的手數。

回測結果

這次製作的馬丁格爾EA與上次製作的只開一部位EA的回測結果進行比較。

回測條件如下。
    貨幣對:GBPUSD
    時間週期:5分鐘
    時間:從2018年1月1日至2023年1月1日的5年時間
    點差:固定為15

一部位EA

一部位EA

馬丁格爾EA

馬丁格爾EA

可以看到,在曲線圖的下方有顯示綠色柱狀圖

這是下單時的手數。

也就是說,綠色柱狀長的地方也就是連續虧損的地方。

從成績上來說,在交易次數、盈利因子、勝率等項目中高於一部位EA。

但是,由於手數會增加,所以最大回撤也高於一部位EA。

主要事項

這次回測是在固定點差中進行。

台灣時間早盤的特徵是,市場波動相對較小,點差容易擴大。

在實際操作中需要充分注意點差,對點差設置限制等措施。

馬丁格爾策略有可能會在一瞬間就會失去全部資金,在使用時還請多加注意。

完整源碼

#property copyright "Copyright(C) 2023, VEXI"
#property link "https://www.mql5.com"
#property version "1.00"
#property strict

input int MAGICMA = 23198721; // Magic Number
input double Lots =0.01; // 1手為10萬貨幣
input int Slippage = 4; // 限制下單滑點
input double MaxSpread = 5; // 限制下單點差
input double TakeProfit = 10.0; // 停利點數(pips)
input double LossCut = 20.0; // 停損點數(pips)
input int RSIPeriod=6; // 週期
input ENUM_APPLIED_PRICE RSIAppliedPrice = PRICE_CLOSE; // 價格來源
input int UpLine = 85; // 上線
input int DownLine = 25; // 下線
input int TradeTime = 0; // 交易時間

//設置馬丁格爾
input int NumMartin = 5; // 在馬丁格爾中加倍加碼的最大次數

double dSpread;

int OnInit()
{
return(INIT_SUCCEEDED);
}
void OnTick()
{
dSpread = (Ask - Bid) / (Point * 10);

int loseCount = 0; //虧損次數
for( int i= OrdersHistoryTotal()-1; i>=0; i-- ){
if( OrderSelect(i, SELECT_BY_POS, MODE_HISTORY) == true && OrderMagicNumber() == MAGICMA && OrderSymbol() == Symbol() ){
if( OrderProfit() <= 0 ){
if(loseCount >= NumMartin)break;
loseCount++;
}
else{
break;
}
}
}
double lot = Lots * MathPow(2, loseCount);
if(CalculateCurrentOrders()==0 && dSpread < MaxSpread) CheckForOpen(lot);

}
void CheckForOpen(double lot)
{
int res;
double RSI = iRSI(Symbol(), 0, RSIPeriod, RSIAppliedPrice, 1);
if(TradeTime == TimeHour(Time[1]))
{
if(RSI < DownLine)
{
res=OrderSend(Symbol(), OP_BUY, lot, Ask, Slippage, Bid - LossCut * Point * 10, Ask + TakeProfit * Point * 10,"", MAGICMA, 0, Red);
}
if(RSI > UpLine)
{
res=OrderSend(Symbol(), OP_SELL, lot, Bid, Slippage, Ask + LossCut * Point * 10, Bid - TakeProfit * Point * 10, "", MAGICMA, 0, Blue);
}
}
}

int CalculateCurrentOrders()
{
int positions = 0;
for(int i=0;i {
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;
if(OrderSymbol()==Symbol() && OrderMagicNumber()==MAGICMA)
{
positions++;
}
}
return positions;
}
[faq slug="faq_ea95"]

將EA自動程式交易應用於外匯與差價合約交易中

EA

我們以圖文形式詳細介紹有關EA自動程式交易的基本知識,以及在MT4/MT5平台上的安裝、參數設定方法、編碼等等內容。另外,對持有VEXI帳戶的客戶,還可以免費使用我們的獨有EA與指標工具。

]]>
一部位EA 馬丁格爾EA EA
在早盤頭皮EA中加入同時持有多個部位的功能【複製源碼就可以使用】 https://www.vexifx.com/bvi-ft/lab-education/ea_trading/multiple_simultaneous_possession/ Tue, 22 Aug 2023 01:04:04 +0000 https://www.vexifx.com/bvi-ft/lab-education/?post_type=ea_trading&p=35917 在早盤頭皮EA中加入同時持有多個部位的功能【複製源碼就可以使用】
在之前的文章介紹了透過簡單的時間限制和逆勢交易就可以取得良好的回測結果。

本篇文章將介紹在之前製作的EA中加入各種功能時又會出現什麼樣的變化。

上次的EA只可以持有一個部位。

這次修改為可以同時持有多個部位。

同時持有部位的數量對EA的影響

首先介紹同時增加持有部位數量時的優點和缺點。

<優點>

最大的優點就是,不會錯過下單的機會,並且可以擴大盈利。

單倉EA在持有部位時不能增加新的部位。

因此,在持有部位時即便出現絕好的下單機會也只能錯過。

另外一個優點就是,透過連續下單可以像加倉一樣可以讓價位更接近盈虧平衡點。

<缺點>

持有的部位越多,當行情走勢相反時的虧損越容易擴大。

雖然部位的最大持有數增加越多,越容易一點一點的積累收益,但是,當出現較大失敗時的虧損也會擴大。

另外,還有一個缺點就是很難管理手數。

很多外匯平台都會在保證金維持率低於一定數值時執行強制平倉。

由於持有部位就會降低保證金維持率,因此有必要提前計算出「幾手的話可以持有幾個部位」。

說明

・下單

時間在日本時間清晨,並且RSI低於超賣線時下多單

時間在日本時間清晨,並且RSI高於超買線時下空單

・平倉

根據停利價格和停損價格平倉

・其他

Copyright設置為「VEXI」

透過滑點和點差限制下單數量

設置為只能持有1個部位

可以修改Magic Number和手數

以上內容是上次製作的EA。

這次把「其他」中的「同時只持有一個部位」修改為「可以在參數中設置同時持有的部位數量」。

製作EA

本程式是以上次的「製作早盤頭皮EA」為基礎製作,所以跳過上次內容,本篇文章至介紹加入的功能。

// Magic Number
input double Lots =0.01; // 1手為10萬貨幣
input int Slippage = 4; // 限制下單滑點
input double MaxSpread = 5; // 限制下單點差
input double TakeProfit = 30.0; // 停利點數(pips)
input int RSIPeriod=6; // 週期
input ENUM_APPLIED_PRICE RSIAppliedPrice = PRICE_CLOSE; // 價格來源
input int UpLine = 85; // 上線
input int DownLine = 25; // 下線
input int TradeTime = 0; // 交易時間
input int MaxPositions = 5; // 部位最大持有數

double dSpread;
在上次的程式中添加了「部位最大持有數」參數。

在這個參數中可以設置同時持有的部位數量。

OnTick函數

void OnTick()
{
dSpread = (Ask - Bid) / (Point * 10);
//if(CalculateCurrentOrders()==0 && dSpread < MaxSpread) CheckForOpen(); 上次
if(CalculateCurrentOrders() < MaxPositions && dSpread < MaxSpread && Volume[0] == 1) CheckForOpen(); //這次

}
以上為OnTick函數。

上次,根據「CalculateCurrentOrders()==0」條件「持有部位數為0時下單」,這次,條件修改為「CalculateCurrentOrders() < MaxPosition」,這樣就可以在參數中設置同時持有的部位數量。

另外,又添加了一個新的條件「Volume[0] == 1」。

Volume[0]是指取得當前K線的成交量數量。

「Volume[0] == 1」是「當前K線的成交量是第一個時」,也就是添加了「K線形成瞬間」這個條件。

因為比較難以理解,下面介紹有和沒有「Volume[0] == 1」時會有什麼不同。

・沒有「Volume[0] == 1」時

以下是可視模式下的回測結果。

可視模式下的回測結果

雖然從圖中很難看出,在同一根K線連續持有了5個多單。

這個動作不太好。

因為這樣就浪費了下單時的點差,這樣的話不如加大手數只持有一個部位。

・有「Volume[0] == 1」時

以下為添加「Volume[0] == 1」的結果。

「Volume[0] == 1」的結果

可以看出,因為添加了「Volume[0] == 1」,所以只會在每根K線第一個Tick時下單。

回測結果

這次製作的最多可持有5個部位的EA與上次製作的只開一部位EA的回測結果進行比較。

回測條件如下。
    貨幣對:GBPUSD
    時間週期:5分鐘
    時間:從2018年1月1日至2023年1月1日的5年時間
    點差:固定為15

・一部位EA

一部位EA

・最多可持有5個部位EA

部位最大持有數 需要關注的是「交易總計」和「盈利因子」。

這次因為可以設置「部位最大持有數」,所以交易總計由511次增加到987次。

另外,因為指定「部位最大持有部位數」添加了類似加倉的功能,沒有錯過下單機會,盈利因子也有1.21上升到1.85。

單倉EA和多倉EA之間似乎沒有明顯的差異,但是,設置為多倉EA也可以帶來多種優點。

主要事項

這次回測是在固定點差中進行。

亞洲時間早盤的特徵是,市場波動相對較小,點差容易擴大。

在實際操作中需要充分注意點差,對點差設置限制等措施。

完整源碼

#property copyright "Copyright(C) 2023, VEXI"
#property link "https://www.mql5.com"
#property version "1.00"
#property strict

// Magic Number
input double Lots =0.01; // 1手為10萬貨幣
input int Slippage = 4; // 限制下單滑點
input double MaxSpread = 5; // 限制下單點差
input double TakeProfit = 30.0; // 停利點數(pips)
input int RSIPeriod=6; // 週期
input ENUM_APPLIED_PRICE RSIAppliedPrice = PRICE_CLOSE; // 價格來源
input int UpLine = 85; // 上線
input int DownLine = 25; // 下線
input int TradeTime = 0; // 交易時間
input int MaxPositions = 5; // 部位最大持有數

double dSpread;

int OnInit()
{
return(INIT_SUCCEEDED);
}
void OnTick()
{
dSpread = (Ask - Bid) / (Point * 10);
if(CalculateCurrentOrders() < MaxPositions && dSpread < MaxSpread && Volume[0] == 1) CheckForOpen();

}
void CheckForOpen()
{
int res;
double RSI = iRSI(Symbol(), 0, RSIPeriod, RSIAppliedPrice, 1);
if(TradeTime == TimeHour(Time[1]))
{
if(RSI < DownLine)
{
res=OrderSend(Symbol(), OP_BUY, Lots, Ask, Slippage, Bid - LossCut * Point * 10, Ask + TakeProfit * Point * 10,"", MAGICMA, 0, Red);
}
if(RSI > UpLine)
{
res=OrderSend(Symbol(), OP_SELL, Lots, Bid, Slippage, Ask + LossCut * Point * 10, Bid - TakeProfit * Point * 10, "", MAGICMA, 0, Blue);
}
}
}

int CalculateCurrentOrders()
{
int positions = 0;
for(int i=0;i {
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;
if(OrderSymbol()==Symbol() && OrderMagicNumber()==MAGICMA)
{
positions++;
}
}
return positions;
}
[faq slug="faq_ea94"]

將EA自動程式交易應用於外匯與差價合約交易中

EA

我們以圖文形式詳細介紹有關EA自動程式交易的基本知識,以及在MT4/MT5平台上的安裝、參數設定方法、編碼等等內容。另外,對持有VEXI帳戶的客戶,還可以免費使用我們的獨有EA與指標工具。

]]>
可視模式下的回測結果 「Volume[0] == 1」的結果 一部位EA 部位最大持有數 EA
什麼是均值回歸策略?介紹使用共整合ADF檢定的交易策略 https://www.vexifx.com/bvi-ft/lab-education/ea_trading/mean_reversion_strategy/ Mon, 21 Aug 2023 00:56:01 +0000 https://www.vexifx.com/bvi-ft/lab-education/?post_type=ea_trading&p=35918 什麼是均值回歸策略?介紹使用共整合ADF檢定的交易策略
均值回歸策略是在量化交易中常用的一種交易策略。

如果在價格變動中可以發現不隨機的均值回歸慣性的話,就可以在超買時賣出、超賣時買入,從而在交易中獲得優勢。

本篇文章將介紹作為均值回歸策略的統計套利(Statistical Arbitrage:StatArb)以及從數學上產生均值回歸慣性的共整合法。

統計套利

統計套利是均值回歸策略中的一種。

一般常見的統計套利就是根據2種交易品種的相對價格進行交易判斷。

也就是說,並不是直接判斷超買超賣,而是相對與其他品種,該品種是超買還是超賣。

雖然是套利交易,但是與無風險且有利可圖的套利不同,這是一種在短期內並不知道是否會出現盈虧,是需要多次測試,從長期來看可以盈利的交易策略之一。

下面介紹一個統計套利的一個實例。

2個交易品種的組合最好具有很高的相關性。

當2個具有相關性的品種的價格差(點差)出現均值回歸時,就會產生統計套利的機會。

在價格差出現均值回歸慣性時,在點差暫時擴大後回歸到均值時可以做多或做空。

價格差出現均值回歸慣性

在判斷與其他品種相比是否超買或超賣時,如果可以從經濟學觀點上解釋其中一個品種與另外一個品種的相關性是高估還是低估時,可以提高判斷的準確度。

什麼是均值回歸

透過隨機與均值回歸相比較,確認在時間序列數據中均值回歸是什麼樣的狀態。

隨機的示例

隨機的示例

均值回歸的示例

均值回歸的示例

隨機走勢是指在前一個數據中加入隨機數據的時間序列數據,均值回歸是在時間序列的中心有一個軸心,隨機就像是在其附近不均衡的變化數據。

隨機走勢就是一種價格決定與過去數據無關的狀態。

一個時間序列的均值和方差保持不變的特性被稱為靜止性。

這種靜止性或者靜止性所擁有的可以顯示靜止過程,是分析時間序列時非常重要的概念。

為了了解什麼是靜止過程,需要確認滯後1的自回歸過程(AR(1)過程)是否處於靜止狀態。

AR(1)過程是指「依賴前一個數據的時間序列的靜止過程」,代表現在的行情與前一個行情具有一定相關性的時間序列數據。

AR(1)過程

AR(1)過程可以用以上公式表示。

白噪音是時間序列數據的隨機成分。

為了可以更加容易理解,這裡將常數項一直視為0。

曲線圖

從左至右是顯示φ = -0.5、φ = 0.0、φ = 0.5、φ=1.0變化的曲線圖。

當φ = -0.5時,上下震盪最為劇烈,越往右邊來,曲線圖的震盪就越加平穩。

當φ = 1.0是,時間序列數據是在前一個數據中加入了隨機數據,這個條件與隨機走勢一樣,不會回歸到均值。

這種 φ的絕對值小於 1.0 的時間序列數據被稱為靜止過程,而 φ = 1.0 的時間序列數據被稱為單位根過程。

成為靜止過程,代表擁有回歸均值的特性。

在判斷均值回歸策略是否成立時,確認時間序列是否有靜止過程也是一種方法。

確認時間序列數據是否有靜止的方法之一就是ADF檢定。

ADF檢定是一種假設「時間序列有單位根」的檢定。

如果不具有這一假設的話,也就代表這個時間序列很有可能不是隨機走勢。

下面介紹一個使用Python的statsmodels庫進行ADF檢定的示例。

```
import yfinance as yf
from statsmodels.tsa.stattools import adfuller

# 獲取USD/JPY的數據
pair = 'JPY=X'
data = yf.download(pair, start='2022-04-01', end='2022-09-01')
usd_jpy_data = data['Close']

# ADF檢定
adf_test_result = adfuller(usd_jpy_data)
# 顯示結果
print('ADF Statistic:', adf_test_result[0])
print('p-value:', adf_test_result[1])
print('Critical Values:')
for key, value in adf_test_result[4].items():
print('\t%s: %.3f' % (key, value))
```
USD/JPY的數據 輸出數據如下。
    1.檢定統計數
    2.p值
    3.檢定統計數的拒絕極限(1%、5%、10%)
如果可以簡單的拒絕p值(p-value)小於0.05的零假設,那麼結果就是無法拒絕時間序列具有單位根的零假設,也就是不能否定會遵循隨機走勢。

透過共整合進行配對交易

實際上,只用一種品種的話很難查到均值回歸性質。

需要用2種品種之間的差確認是否會出現均值回歸性質。

如果在具有相關性的2種品種之間的點差出現均值回歸的話,可以利用多空組合來獲利。

共整合ADF檢定就是可以尋找提供此類交易機會的貨幣對的統計方法。

共整合ADF檢定就是對2種時間序列數據進行線形回歸,檢定殘差序列的靜止性。

當2個時間序列數據的線形組合是一個靜止過程時,線形回歸的殘差序列也是靜止的。

下面介紹一個使用Python的statsmodels庫進行共整合ADF檢定的示例。
```
import yfinance as yf
import pandas as pd
import statsmodels.tsa.stattools as ts

# 獲取每個貨幣對的數據
pairs = ['AUDJPY=X', 'CADJPY=X']
fx_data = {}
for pair in pairs:
data = yf.download(pair, start='2022-01-01', end='2023-01-01')
fx_data[pair] = data['Close']

merged_data = pd.DataFrame(fx_data)

# 刪除缺失值
merged_data.dropna(inplace=True)

# 共整合ADF検定
eg_test_result = ts.coint(merged_data['AUDJPY=X'], merged_data['CADJPY=X'])

# 顯示結果
print('T-statistic:', eg_test_result[0])
print('p-value:', eg_test_result[1])
print('Critical Values:')
critical_value_labels = ['1%', '5%', '10%']
for i, value in enumerate(eg_test_result[2]):
print('\t%s: %.3f' % (critical_value_labels[i], value))
```
獲取每個貨幣對的數據

輸出數據如下。
    1.檢定統計數
    2.p值
    3.極限值
如果可以簡單的認為p值(p-value)小於0.05時就可以拒絕零假設時,結果就與共整合沒有任何關係了。

利用以上步驟來需要擁有與共整合相關的貨幣對,當找到的貨幣對的點差暫時擴大做多或做空,等待均值回歸,這樣就可以進行超出預期值的交易(配對交易)。

做多或做空的時機

對於根據共整合ADF檢定找出與共整合相關的貨幣對後,就可以使用均值回歸策略。只需要在「殘差時間序列圖」上畫一條顯示平均值和標準偏差的水平線,就可以利用它來確定下單的時機。

曲線圖

上方的曲線圖是重疊顯示了用共整合ADF檢定找出的貨幣對(symbol1和symbol2)的價格變動。下方的曲線圖是當貨幣對回歸時的殘差時間序列圖。

在平均值與平均值之間畫一條±2σ的水平線。

在+2σ線的上方時賣出symbol1、同時買入symbol2,然後等待均值回歸時的價格變動。

下面介紹如何利用布林通道來確認交易時機。

布林通道

如果按照一般的方法,當觸及布林通道的上軌或下軌時反向交易的話,在有趨勢的行情中會出現巨大虧損,而且在隨機走勢中也沒有任何優勢。

處於共整合關係中的貨幣對會有靜態殘差序列,就像是在震盪行情中使用布林通道做反向交易一樣。

如何尋找統計套利交易的機會

資源國際貨幣與一部分的大宗商品配對時,有可能會出現相關性。

下圖是根據共整合檢定的p值所計算出的多個資源國際貨幣與大宗商品配對時的相關性。

多個資源國際貨幣

因為p值越低共整合相關性的可能性越高,所以上圖中的深藍色配對組合屬於這種情況。

這樣用相關性圖顯示出來的話,就可以更加有效的找到配對組合。

下圖是顯示共整合檢定的p值時間變化。

整合檢定的p值時間變化

雖然上圖數據的配對組合並不是整體上都有共整合關係,但是,可以看出p值下降的時機存在週期性。

即使只是暫時會出現統計套利交易的機會,如果這個時機可以預測的話就有交易的可能性。

評價性能時的注意點

並不只限於統計套利交易,在其他交易中也是,如果想要用過去的歷史數據來評價策略的表現的話,需要複製現實情況進行測試才可以。

共整合檢定

如上圖所顯示的策略表現,如果在共整合檢定時,事前已經知道「在這一期間會出現均值回歸」,然後用相關策略進行測試的話,就會成為失敗的檢定。

在現實情況中,在開始交易之前還不知道什麼時候會出現均值回歸,需要預測「會出現均值回歸」,然後用相關策略進行交易。

共整合檢定

上圖顯示,透過共整合檢定發現均值回歸的配對組合後,預測「隨後的期間也會持續均值回歸」,然後用相關策略進行交易,這樣的測試就再現了現實情況。

關於統計套利交易的研究

配對交易或統計套利交易自20世紀80年代以來一直被用於交易中,許多量化交易者和研究人員也從那時起對其進行了開發。

現在,其中很多都融入了機器學習技術。

在此介紹部分文獻。

Kitapbayev Y. and Leung T. (2017).「Optimal mean-reverting spread trading: nonlinear integral equation approach.」

關於下單和平倉的時間會有多種方法。

以上文獻中介紹,在OU過程(Ornstein-Uhlenbeck process 均值回歸的隨機過程 )中應用最佳停止問題,透過衡量下單和平倉的時間來實現高收益。

Beckmann J, Czudaj R, Arora V (2017) 「The Relationship Between Oil Prices And Exchange Rates: Theory And Evidence」

出現共整合關係的背景是對於相關品種的當前價格,可以用另一個配對品種來評價是否被高估或低估。

以上文獻研究了原油價格和外匯匯率之間的相互影響關係。

為原油價格和外匯匯率之間是否存在以上的高估或低估關係提供了線索。

Figueira M, and Horta N (2022)「Machine Learning-Based Pairs Trading Strategy with Multivariate」

以上文獻提供了可以利用機器學習(ARIMAとXGBoost)从2種以上的品種的多變量配對組合的點差中發現交易機會的方法。

統計套利交易雖然是從相對價格評價中發現也預測的機會,但並不一定是2種品種。

如果點差存在可預測的週期或模式的的話,也不一定需要均值回歸策略。

關於多變量配對組合(Johansen檢定)

本篇文章雖然介紹了共整合ADF檢定(Engle-Granger檢定),其實還有另外一種方法就是Johansen檢定(Johansen test)。

Engle-Granger的方法是分析2個變量的共整合,而Johansen的方法是同時推測和分析3個變量以上的共整合。

以下Python源碼是Johansen檢定的示例。
```
import yfinance as yf
import pandas as pd
from statsmodels.tsa.vector_ar.vecm import coint_johansen

# 獲取每個貨幣對的數據
pairs = ['AUDJPY=X', 'CADJPY=X', 'NZDJPY=X']
fx_data = {}
for pair in pairs:
data = yf.download(pair, start='2022-01-01', end='2023-01-01')
fx_data[pair] = data['Close']

merged_data = pd.DataFrame(fx_data)

# 刪除缺失值
merged_data.dropna(inplace=True)

# Johansen共整合檢定
result = coint_johansen(merged_data, det_order=0, k_ar_diff=1)

# 顯示結果
print("\n\n追蹤檢定統計量:")
for i, trace_stat in enumerate(result.lr1):
print(f"r = {i}: {trace_stat}")
print("\n追蹤檢定的極限:")
for i, trace_crit in enumerate(result.cvt):
print(f"r = {i}: 1% = {trace_crit[0]}, 5% = {trace_crit[1]}, 10% = {trace_crit[2]}")
print("\n最大特徵值檢定統計量:")
for i, max_eig_stat in enumerate(result.lr2):
print(f"r = {i}: {max_eig_stat}")
print("\n最大特徵值檢定的極限:")
for i, max_eig_crit in enumerate(result.cvm):
print(f"r = {i}: 1% = {max_eig_crit[0]}, 5% = {max_eig_crit[1]}, 10% = {max_eig_crit[2]}")
```
共整合ADF檢定

共整合ADF檢定會進行2個變量回歸。

也就是,一個是因變量,另一個是解釋變量,但當樣本量較小時,因變量和解釋變量調換,結果就會發生變化。

另外, 還沒有建立系統的程序來推測3個變量以上的共整合。

Johansen檢定因為不需要共整合AD檢定的兩階段程序,所以不會出現這些問題,可以檢定多變量配對組合。

3種以上品種的多變量配對組合之間確實存在相關性,其點差中可能會出現可預測的週期或模式,例如,有可能會出現領先或落後等關係。 [faq slug="faq_ea93"]

將EA自動程式交易應用於外匯與差價合約交易中

EA

我們以圖文形式詳細介紹有關EA自動程式交易的基本知識,以及在MT4/MT5平台上的安裝、參數設定方法、編碼等等內容。另外,對持有VEXI帳戶的客戶,還可以免費使用我們的獨有EA與指標工具。

]]>
價格差出現均值回歸慣性 隨機的示例 均值回歸的示例 AR(1)過程 曲線圖 USD/JPY的數據 獲取每個貨幣對的數據 曲線圖 布林通道 多個資源國際貨幣 整合檢定的p值時間變化 共整合檢定 共整合檢定 共整合ADF檢定 EA
在早盤頭皮EA中加入追蹤停損功能【複製源碼就可以使用】 https://www.vexifx.com/bvi-ft/lab-education/ea_trading/beginner-trailingstop/ Mon, 14 Aug 2023 01:58:51 +0000 https://www.vexifx.com/bvi-ft/lab-education/?post_type=ea_trading&p=35859 在早盤頭皮EA中加入追蹤停損功能【複製源碼就可以使用】
本篇文章並不是確認「最大持倉數量」,而是測試加入「追蹤停損」功能後會有什麼樣的結果。

追蹤停損的優點與缺點

首先介紹一下追蹤停損的優點與缺點。

<優點>

優點是即可以控制風險還可以擴大收益。

由於追蹤停損被執行時停損點就會被提高,所以,與簡單的停損停利的結算方式相比,獲利的機會更大。

<缺點>

其缺點就是,在產生小幅盈利時就會結算,從而錯失本可以獲得更大利潤。

為了防止小幅盈利,需要緊密調整追蹤停損的幅度。

如果追蹤停損的幅度設置不正確的話,有可能會出現「輕微反彈就馬上結算」或「追蹤停損本身不會被執行」。

    追蹤停損的種類

    加入追蹤停損時有多種方法。

    例如,「當達到一定收益幅度時上移停損點」、「產生一點收益就上移停損點」、「根據行情趨勢修改幅度」等方法。

    追蹤停損如果與EA邏輯相匹配的話,將會成為擴大收益的有力武器。

說明

首先介紹上次製作的EA。

・下單

時間在台灣時間清晨,並且RSI低於超賣線時下多單

時間在台灣時間清晨,並且RSI高於超買線時下空單

・平倉

根據停利價格和停損價格平倉

・其他

Copyright設置為「VEXI」

透過滑點和點差限制下單數量

設置為只能持有1個部位

可以修改Magic Number和手數

以上內容是上次製作的EA。

這次將會用追蹤停損來控制停損,所以要把平倉邏輯「根據停損價格平倉」修改為「根據追蹤停損來停損平倉」。

製作EA

本程式是以上次的「製作早盤頭皮EA」為基礎製作,所以跳過上次內容,本篇文章至介紹加入的功能。

領域

input int MAGICMA = 23498721; // Magic Number
input double Lots =0.01; // 1手為10萬貨幣
input int Slippage = 4; // 限制下單滑點
input double MaxSpread = 5; // 限制下單點差
input double TakeProfit = 30.0; // 停利點數(pips)
input int RSIPeriod=6; // 週期
input ENUM_APPLIED_PRICE RSIAppliedPrice = PRICE_CLOSE; // 價格來源
input int UpLine = 85; // 上線
input int DownLine = 25; // 下線
input int TradeTime = 0; // 交易時間
input int TrailWidth = 10; // 追蹤幅度(pips)

double dSpread;
在上次程式中,刪除了「停損點數(pips)」,新添加了「追蹤幅度(pips)」參數。

OnTick函數

void OnTick()
{
dSpread = (Ask - Bid) / (Point * 10);
if(CalculateCurrentOrders()==0 && dSpread < MaxSpread) CheckForOpen(); 上次
TrailingStop(); //這次

}
這是OnTick函數。

這次準備了一個簡單易懂的TrailingStop函數,只需在OnTick函數中調用該函數就可以執行追蹤停損。

CheckForOpen函數

void CheckForOpen()
{
int res;
double RSI = iRSI(Symbol(), 0, RSIPeriod, RSIAppliedPrice, 1);
if(TradeTime == TimeHour(Time[1]))
{
if(RSI < DownLine)
{
res=OrderSend(Symbol(), OP_BUY, Lots, Ask, Slippage, Bid - TrailWidth * Point * 10, Ask + TakeProfit * Point * 10,"", MAGICMA, 0, Red);
}
if(RSI > UpLine)
{
res=OrderSend(Symbol(), OP_SELL, Lots, Bid, Slippage, Ask + TrailWidth * Point * 10, Bid - TakeProfit * Point * 10, "", MAGICMA, 0, Blue);
}
}
}
把OrderSend函數的停損價格修改為TrailWidth參數。

這樣,TrailWidth數值就會成為持有部位時停損幅度。

TrailingStop函數

for (int i = OrdersTotal() - 1; i >= 0; i--){
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;
if (OrderType() == OP_BUY){
if ((Bid - OrderStopLoss()) / (Point * 10) > TrailWidth * 2){ //①
int om = OrderModify(OrderTicket(), //②
OrderOpenPrice(),
OrderStopLoss() + TrailWidth * (Point * 10),
OrderTakeProfit(),
OrderExpiration());
}
}
if (OrderType() == OP_SELL){
if ((OrderStopLoss() - Ask) / (Point * 10) > TrailWidth * 2){ //①
int om = OrderModify(OrderTicket(), //②
OrderOpenPrice(),
OrderStopLoss() - TrailWidth * (Point * 10),
OrderTakeProfit(),
OrderExpiration());
}
}
}
操作很簡單,對持有的部位執行2個處理,「①確認是否滿足追蹤停損的條件」、「②如果滿足追蹤停損條件,使用OrderModify函數上移停損點」。

接下來逐一介紹關於2個處理的內容。

①確認是否滿足追蹤停損的條件

if ((Bid - OrderStopLoss()) / (Point * 10) > TrailWidth * 2){
以買入部位為例。

左邊是在求當前價格和停損價格的幅度(pips),然後判斷其數字是否大約TrailWidth參數的2倍數值。這裡設置為TrailWidth 的2倍是一個重要的點。

因為左邊不是「當前價格和下單價格的幅度」,而是「當前價格和停損價格的幅度」,所以需要設置為2倍。

②使用OrderModify函數上移停損點

int om = OrderModify(OrderTicket(),
OrderOpenPrice(),
OrderStopLoss() - TrailWidth * (Point * 10),
OrderTakeProfit(),
OrderExpiration());
第3個參數是指定停損價格的參數。

如果滿足追蹤停損的條件的話,停損點將會按照TrailWidth參數的數值上移。

回測結果

這次製作的追蹤停損EA與上次製作的只開一部位EA的回測結果進行比較。
貨幣對:GBPUSD 時間週期:5分鐘 時間:從2018年1月1日至2023年1月1日的5年時間 點差:固定為15
    貨幣對:GBPUSD
    時間週期:5分鐘
    時間:從2018年1月1日至2023年1月1日的5年時間
    點差:固定為15

・一部位EA

一部位EA

・追蹤停損EA

追蹤停損EA

「交易次數」從511次上升至714次。

這是因為追蹤停損把停損點上移,與平常的停損邏輯相比會提前平倉。

另外,從曲線圖中也可以看出,一部位EA有很多波折,而追蹤停損EA會更加平滑。

這種曲線圖的形狀也是追蹤停損EA的特徵之一。

但是,「勝率」且大幅下降到35.29%。

這也是因為追蹤停損EA的會提前停損,反而證明了可以穩定盈利。

關於勝率,如果對參數進行優化的話還有可能會提升。

注意事項

這次回測是在固定點差中進行。

台灣時間早盤的特徵是,市場波動相對較小,點差容易擴大。

在實際操作中需要充分注意點差,對點差設置限制等措施。

完整源碼

#property copyright "Copyright(C) 2023, VEXI"
#property link "https://www.mql5.com"
#property version "1.00"
#property strict

input int MAGICMA = 23498721; // Magic Number
input double Lots =0.01; // 1手為10萬貨幣
input int Slippage = 4; // 限制下單滑點
input double MaxSpread = 5; // 限制下單點差
input double TakeProfit = 30.0; // 停利點數(pips)
input int RSIPeriod=6; // 週期
input ENUM_APPLIED_PRICE RSIAppliedPrice = PRICE_CLOSE; // 價格來源
input int UpLine = 85; // 上線
input int DownLine = 25; // 下線
input int TradeTime = 0; // 交易時間
input int TrailWidth = 10; // 追蹤幅度(pips)

double dSpread;

int OnInit()
{
return(INIT_SUCCEEDED);
}
void OnTick()
{
dSpread = (Ask - Bid) / (Point * 10);
if(CalculateCurrentOrders()==0 && dSpread < MaxSpread) CheckForOpen();
TrailingStop();
}
void CheckForOpen()
{
int res;
double RSI = iRSI(Symbol(), 0, RSIPeriod, RSIAppliedPrice, 1);
if(TradeTime == TimeHour(Time[1]))
{
if(RSI < DownLine)
{
res=OrderSend(Symbol(), OP_BUY, Lots, Ask, Slippage, Bid - TrailWidth * Point * 10, Ask + TakeProfit * Point * 10,"", MAGICMA, 0, Red);
}
if(RSI > UpLine)
{
res=OrderSend(Symbol(), OP_SELL, Lots, Bid, Slippage, Ask + TrailWidth * Point * 10, Bid - TakeProfit * Point * 10, "", MAGICMA, 0, Blue);
}
}
}

int CalculateCurrentOrders()
{
int positions = 0;
for(int i=0;i= 0; i--){
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;
if (OrderType() == OP_BUY){
if ((Bid - OrderStopLoss()) / (Point * 10) > TrailWidth * 2){
int om = OrderModify(OrderTicket(), OrderOpenPrice(), OrderStopLoss() + TrailWidth * (Point * 10), OrderTakeProfit(), OrderExpiration());
}
}
if (OrderType() == OP_SELL){
if ((OrderStopLoss() - Ask) / (Point * 10) > TrailWidth * 2){
int om = OrderModify(OrderTicket(), OrderOpenPrice(), OrderStopLoss() - TrailWidth * (Point * 10), OrderTakeProfit(), OrderExpiration());
}
}
}
}
[faq slug="faq_ea92"]

將EA自動程式交易應用於外匯與差價合約交易中

EA

我們以圖文形式詳細介紹有關EA自動程式交易的基本知識,以及在MT4/MT5平台上的安裝、參數設定方法、編碼等等內容。另外,對持有VEXI帳戶的客戶,還可以免費使用我們的獨有EA與指標工具。

]]>
一部位EA 追蹤停損EA EA
外匯交易中的EA是什麼?介紹如何使用移動平均線(MA)製作一個簡單的EA https://www.vexifx.com/bvi-ft/lab-education/ea_trading/ma_expert_adviser/ Fri, 28 Jul 2023 01:05:52 +0000 https://www.vexifx.com/bvi-ft/lab-education/?post_type=ea_trading&p=35695 什麼是EA(自動交易)?說明使用移動平均線(MA)製作一個簡單的EA

什麼是EA?

EA是Expert Adviser的簡稱,是一種可以代替交易者進行自動交易的程式。

EA有多種類型,有從下單到平倉全部程序都自動交易型,還有只在平倉時手動的半自動型。

本篇文章將介紹如何製作一個簡單的EA。

    所有的自動交易都是EA嗎?

    雖然把自動交易程式稱為EA,實際上主要是對於MT4或MT5中所製作的程式。

    在外匯交易中除了EA之外,還有外匯經紀商獨自的自動交易程式。

    另外,在加密貨幣的行業中,把自動交易程式稱為「bot」,或是直接稱為「自動交易工具」。

規格

首先整理要製作的EA規格。

雖然也可以馬上編寫程式,但是,整理好規格的話可以提高編寫效率。

下單條件

當短期MA和長期MA黃金交叉時下買單。

當短期MA和長期MA死亡交叉時下賣單。

平倉條件

這次,平倉是用手動進行,所以不設置平倉邏輯。

其他條件

透過滑點和點擊來限制下單。

同時只能持有一個部位。

可以修改Magic Number和手數。

製作EA

程式按照「預處理器」、「欄位」、「函數(OnInit)」「函數(OnInit以外)」的順序進行編寫。

函數

預處理器 在mql4程式被編寫之前執行的預處理。
指定程式版權和版本。
欄位 儲存在程式中所使用的的各種數據。
函數 把特定動作同一歸納在一起的部分。

預處理器

#property copyright "Copyright 2018, MetaQuotes Software Corp."
#property link "https://www.mql5.com"
#property version "1.00"
#property strict
在創建新的EA時,默認會提高一個模板方案。

這次製作的EA將使用默認的預處理器。

關於「copyright」和「link」,主要是把製作的EA送給其他人時所顯示部分,如果只是個人使用的話刪除也沒有問題。

欄位

input int MAGICMA = 23498721; // Magic Number
input double Lots =0.01; // 1手為10萬貨幣
input int Slippage = 4; // 限制下單的滑點
input double MaxSpread = 5; // 限制下單的點差
input int MAPeriod1 = 12; // 短期均線週期
input int MAPeriod2 = 96; // 長期均線週期
input ENUM_MA_METHOD MAMethod = MODE_SMA; // 種類
input ENUM_APPLIED_PRICE MAAppliedPrice = PRICE_CLOSE; // 應用價格

double dSpread;
當在欄位中聲明一個變量時,在語句前面加入「input」的話,用戶就可以在MT4中修改參數。

EMA輸入參數

對於這次EA的基本要素「Magic Number」、「手數」、「滑點限制」、「點差限制」、以及決定下單時所使用的移動平均線的「短期週期」、「長期週期」、「種類」、「應用價格」,都可以進行修改。

變量「dSpread」是一個計算和存儲點差值的變量。

OnTick函數

int OnInit()
{
return(INIT_SUCCEEDED);
}
OnInit函數是製作新EA時默認提供的函數。

將EA設置在MT4的圖表上的那一刻,在這個函數中所描述的代碼將會被執行。

因此,在這個OnInit函數內需要描述「設置EA的那一刻就進行處理」。

不過,這次製作的EA不需要在設置的那一刻就進行處理,所以也不需要編寫。

OnInit函數

void OnTick()
{
dSpread = (Ask - Bid) / (Point * 10);
if(CalculateCurrentOrders()==0 && dSpread < MaxSpread) CheckForOpen();
}
OnTick函數與OnInit函數一樣,也是在製作新EA時默認提供的函數。

這個函數是當MT4圖表的Tick每次更新時都會執行。

主要是描述「EA的下單和平倉」等重要處理。

在「dSpread」中將會存儲根據Ask(買値)與Bid(売値)之間的差值所計算的點差值。

點差值根據每個Tick出現變化時,都會在OnTIck函數中進行計算。

「if(CalculateCurrentOrders()==0 && dSpread < MaxSpread) CheckForOpen();」的語句代表「現在持有的部位為0,並且當點差低於在參數中的點差限制時進行下單」。

CalculateCurrentOrders函數是讀取現在持有的部位數量的函數。

CheckForOpen函數是實際進行下單的函數。

OnInit函數與OnTick函數是不是一定需要?

OnInit函數與OnTick函數雖然有默認提供,但是,並不是說一定要描述。

例如,即使刪除OnInit函數也可以編寫。

但是,如果把OnInit函數和OnTick函數都刪除的話,在編寫時就會出現錯誤。

CalculateCurrentOrders函數

int CalculateCurrentOrders()
{
int positions = 0;
for(int i=0;i {
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;
if(OrderSymbol()==Symbol() && OrderMagicNumber()==MAGICMA)
{
positions++;
}
}
return positions;
}
CalculateCurrentOrders函數是讀取當前持有的部位數量。

CheckForOpen函數

void CheckForOpen()
{
int res;
double ma1 = iMA(Symbol(), Period(), MAPeriod1, NULL ,MAMethod ,MAAppliedPrice ,1);
double ma2 = iMA(Symbol(), Period(), MAPeriod2, NULL ,MAMethod ,MAAppliedPrice ,1);
double ma1_before = iMA(Symbol(), Period(), MAPeriod1, NULL ,MAMethod ,MAAppliedPrice ,2);
double ma2_before = iMA(Symbol(), Period(), MAPeriod2, NULL ,MAMethod ,MAAppliedPrice ,2);

if(ma1 > ma2 && ma1_before <= ma2_before)
{
res=OrderSend(Symbol(), OP_BUY, Lots, Ask, Slippage, 0, 0,"", MAGICMA, 0, Red);
}
if(ma1 < ma2 && ma1_before >= ma2_before)
{
res=OrderSend(Symbol(), OP_SELL, Lots, Bid, Slippage, 0, 0, "", MAGICMA, 0, Blue);
}
}
CheckForOpen函數是判斷移動平均線是否黃金交叉或死亡交叉。

如果是黃金交叉的話就買入,如果是死亡交叉的話就賣出。

判斷黃金交叉的條件為「前1根K線的短期移動平均線小於長期移動平均線,而當前K線的短期移動平均線大於長期移動平均線」。

一旦滿足了交叉的條件,就會使用OrderSend函數進行下單。

把第5個參數指定為限制滑點的參數的話,就會自動執行滑點限制。

源碼

#property copyright "Copyright 2018, MetaQuotes Software Corp."
#property link "https://www.mql5.com"
#property version "1.00"
#property strict

input int MAGICMA = 23498721; // Magic Number
input double Lots =0.01; // 1手為10萬貨幣
input int Slippage = 4; // 限制下單的滑點
input double MaxSpread = 5; // 限制下單的點差
input int MAPeriod1 = 12; // 短期均線週期
input int MAPeriod2 = 96; // 長期均線週期
input ENUM_MA_METHOD MAMethod = MODE_SMA; // 種類
input ENUM_APPLIED_PRICE MAAppliedPrice = PRICE_CLOSE; // 應用價格

double dSpread;

int OnInit()
{
return(INIT_SUCCEEDED);
}
void OnTick()
{
dSpread = (Ask - Bid) / (Point * 10);
if(CalculateCurrentOrders()==0 && dSpread < MaxSpread) CheckForOpen();//如果沒有部位的話可以持有部位

}
void CheckForOpen()
{
int res;
double ma1 = iMA(Symbol(), Period(), MAPeriod1, NULL ,MAMethod ,MAAppliedPrice ,1);
double ma2 = iMA(Symbol(), Period(), MAPeriod2, NULL ,MAMethod ,MAAppliedPrice ,1);
double ma1_before = iMA(Symbol(), Period(), MAPeriod1, NULL ,MAMethod ,MAAppliedPrice ,2);
double ma2_before = iMA(Symbol(), Period(), MAPeriod2, NULL ,MAMethod ,MAAppliedPrice ,2);

if(ma1 > ma2 && ma1_before <= ma2_before)
{
res=OrderSend(Symbol(), OP_BUY, Lots, Ask, Slippage, 0, 0,"", MAGICMA, 0, Red);
}
if(ma1 < ma2 && ma1_before >= ma2_before)
{
res=OrderSend(Symbol(), OP_SELL, Lots, Bid, Slippage, 0, 0, "", MAGICMA, 0, Blue);
}
}

int CalculateCurrentOrders()
{
int positions = 0;
for(int i=0;i {
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;
if(OrderSymbol()==Symbol() && OrderMagicNumber()==MAGICMA)
{
positions++;
}
}
return positions;
}
[faq slug="faq_ea91"]

將EA自動程式交易應用於外匯與差價合約交易中

EA

我們以圖文形式詳細介紹有關EA自動程式交易的基本知識,以及在MT4/MT5平台上的安裝、參數設定方法、編碼等等內容。另外,對持有VEXI帳戶的客戶,還可以免費使用我們的獨有EA與指標工具。

]]>
函數 EMA輸入參數 EA
使用源碼介紹如何製作早盤頭皮EA【源碼複製就可以使用】 https://www.vexifx.com/bvi-ft/lab-education/ea_trading/morning_scalping/ Wed, 12 Jul 2023 01:09:42 +0000 https://www.vexifx.com/bvi-ft/lab-education/?post_type=ea_trading&p=34996 如何製作早盤頭皮EA 使用源碼說明

什麼是早盤頭皮?

早盤頭皮是在價格波動比較緩慢的台灣清晨時間進行頭皮交易的策略。

下單的順序是,「價格波動緩慢」→「容易出現震盪行情」→「在超買超賣出現反彈時做反向交易」。

但是,台灣清晨時間是不是真的價格波動緩慢呢?

請看下圖確認。

價格波動緩慢

這是USDJPY的30分鐘圖表。

在指標窗口中所顯示的是交易量。

在MT4中的交易量就是「Tick更新頻度」。

也就是,「在30分鐘裡更新了幾次交易」。

從圖中可以看出,連續出現高峰和低谷,存在著極高和極低的交易量。

這個交易量小的時間點也就是台灣的清晨時間,這時,市場的價格波動也會放緩。

EA說明

首先介紹關於製作的EA內容。

下單

時間在台灣時間清晨,並且RSI低於超賣線時下多單

時間在台灣時間清晨,並且RSI高於超買線時下空單

平倉

根據停利價格和停損價格平倉

其他

Copyright設置為「VEXI」,透過滑點和點差限制下單數量。

設置為只能持有1個部位。

可以修改Magic Number和手數。

製作EA

根據前一篇的「4.使用RSI製作EA」對程式進行時間限制的過濾。

在本篇文章中只描述變更點。

領域

input int MAGICMA = 23498721; // Magic Number
input double Lots =0.01; // 1手為10萬貨幣
input int Slippage = 4; // 限制下單滑點
input double MaxSpread = 5; // 限制下單點差
input double TakeProfit = 10.0; // 停利點數(pips)
input double LossCut = 20.0; // 停損點數(pips)
input int RSIPeriod=6; // 週期
input ENUM_APPLIED_PRICE RSIAppliedPrice = PRICE_CLOSE; // 價格來源
input int UpLine = 85; // 上線
input int DownLine = 25; // 下線
input int TradeTime = 0; // 交易時間

double dSpread;
在上次的程式中添加了「交易時間」參數。

只限在這裡設定的時間才可以進行交易。

VEXI的MT4伺服器時間(0點)為GMT+3、冬時令為+2,與GMT+8的台灣在時間上會有時差。

考慮到時差的話,台灣的清晨(5點~6點)是MT4的0點,所以,這次的「交易時間」參數設置為0。

CheckForOpen函數

void CheckForOpen()
{
int res;
double RSI = iRSI(Symbol(), 0, RSIPeriod, RSIAppliedPrice, 1);
if(TradeTime == TimeHour(Time[1])) //追加
{
if(RSI < DownLine)
{
res=OrderSend(Symbol(), OP_BUY, Lots, Ask, Slippage, Bid - LossCut * Point * 10, Ask + TakeProfit * Point * 10,"", MAGICMA, 0, Red);
}
if(RSI > UpLine)
{
res=OrderSend(Symbol(), OP_SELL, Lots, Bid, Slippage, Ask + LossCut * Point * 10, Bid - TakeProfit * Point * 10, "", MAGICMA, 0, Blue);//
}
}
}
在下單條件中加入了if分鐘,以確定當前時間是否是在參數中所指定的時間。

TimeHour函數把datetime類型的變量作為參數,可以接受到參數的時間(0~23)。

回測結果

下面時這次EA的回測結果。

貨幣對:GBPUSD

時間週期:5分鐘

時間:2018年1月1日~2023年1月1日的5年時間

點差:固定為15

EA的回測結果

可以看到只需要透過時間限制和RSI就可以得到非常優秀的結果。

如果在這個邏輯上再加入指標和追蹤止損的話,就可以開發出更好的EA。

注意事項

這次的回測是在固定點差下進行。

在台灣清晨行情放緩的時間段,點差也會擴大。

如果在實盤中操作時,還請多注意點差,做好點差限制措施。

完整源碼

#property copyright "Copyright(C) 2023, VEXI"
#property link "https://www.mql5.com"
#property version "1.00"
#property strict

input int MAGICMA = 23498721; // Magic Number
input double Lots =0.01; // 1手為10萬貨幣
input int Slippage = 4; // 限制下單滑點
input double MaxSpread = 5; // 限制下單點差
input double TakeProfit = 10.0; // 停利點數(pips)
input double LossCut = 20.0; // 停損點數(pips)
input int RSIPeriod=6; // 週期
input ENUM_APPLIED_PRICE RSIAppliedPrice = PRICE_CLOSE; // 價格來源
input int UpLine = 85; // 上線
input int DownLine = 25; // 下線
input int TradeTime = 0; // 交易時間

double dSpread;

int OnInit()
{
return(INIT_SUCCEEDED);
}
void OnTick()
{
dSpread = (Ask - Bid) / (Point * 10);
if(CalculateCurrentOrders()==0 && dSpread < MaxSpread) CheckForOpen();

}
void CheckForOpen()
{
int res;
double RSI = iRSI(Symbol(), 0, RSIPeriod, RSIAppliedPrice, 1);
if(TradeTime == TimeHour(Time[1]))
{
if(RSI < DownLine)
{
res=OrderSend(Symbol(), OP_BUY, Lots, Ask, Slippage, Bid - LossCut * Point * 10, Ask + TakeProfit * Point * 10,"", MAGICMA, 0, Red);
}
if(RSI > UpLine)
{
res=OrderSend(Symbol(), OP_SELL, Lots, Bid, Slippage, Ask + LossCut * Point * 10, Bid - TakeProfit * Point * 10, "", MAGICMA, 0, Blue);
}
}
}

int CalculateCurrentOrders()
{
int positions = 0;
for(int i=0;i {
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;
if(OrderSymbol()==Symbol() && OrderMagicNumber()==MAGICMA)
{
positions++;
}
}
return positions;
} if(OrderSymbol()==Symbol() && OrderMagicNumber()==MAGICMA)
{
positions++;
}
}
return positions;
}
[faq slug="faq_ea90"]

將EA自動程式交易應用於外匯與差價合約交易中

EA

我們以圖文形式詳細介紹有關EA自動程式交易的基本知識,以及在MT4/MT5平台上的安裝、參數設定方法、編碼等等內容。另外,對持有VEXI帳戶的客戶,還可以免費使用我們的獨有EA與指標工具。

]]>
價格波動緩慢 EA的回測結果 EA
在外匯交易中的過度最佳化是什麼?詳細介紹對策以及回測時的注意事項 https://www.vexifx.com/bvi-ft/lab-education/ea_trading/overfitting_measures_backtest/ Tue, 11 Jul 2023 00:15:53 +0000 https://www.vexifx.com/bvi-ft/lab-education/?post_type=ea_trading&p=34995 在外匯交易中的過度最佳化是什麼?詳細介紹對策以及回測時的注意事項
過度最佳化是在程式交易中真正獲取盈利的主要障礙之一。

找到有優勢的策略非常重要,如果不能判斷所使用的程式是否有優勢,就不能獲取盈利。

本篇文章將介紹如何避免過度最佳化,如果透過回測看出程式的真實情況。

表面上的優勢

一個可以檢測出價格波動非隨機性的週期和條件,並能在正確時間採取正確方向部位的程式,在實盤操作中也可以獲取盈利。

如果在持倉期間,價格走勢是隨機或是找不到建倉的方向的話,那麼任何邏輯都不會帶來優勢。

在開發程式中,為了最佳化參數、修改邏輯、增加過濾器等目的,有可能會多次來回查看相同歷史數據。

在來回修改的過程中,程式設置就會最佳化為不能預測隨機的價格波動,因此就會出現不能複製的表面優勢。

因為時不能複製的優勢,所以在實盤中會起不到任何作用。

樣本外測試(Out-of-sample test)

在過度最佳化對策中,廣泛使用的有效措施就是樣本外測試。

如果過度最佳化是由於在同一歷史數據上來回往返所造成的話,在來回往返的程式調整期間之外,需要留出只能一次通過的程式測試期間,這將成為收集現實驗證數據的有效方法。

回測的目的時驗證而不是調整程式。

回測是為了淘汰沒有優勢的程式,而不是為了改善程式進行回測。

從調整程式的數據中挑選出令人滿意的數據,並把它當做歷史表現,這將是一個非常嚴重的問題。

在樣本外測試中最具有代表性的方法就是先行走勢法

下圖是使用2013年初至2022年末為止的歷史數據進行的先行走勢測試。

歷史數據的走勢測試

藍色是程式的最佳化訓練期間(樣本內),綠色是測試期間(樣本外)。
    1.在2013~2016年進行最佳化,在2017年進行測試
    2.在2014~2017年進行最佳化,在2018年進行測試
    3.在2015~2018年進行最佳化,在2019年進行測試
    4.在2016~2019年進行最佳化,在2020年進行測試
    5.在2017~2020年進行最佳化,在2021年進行測試
    6.在2018~2021年進行最佳化,在2022年進行測試
按照以上順序進行回測複製了接近實盤的交易情況,並收集了2017年至2021年為止的測試數據。

訓練數據(樣本內)由於是在歷史數據來回往返的非現實數據,所以,這個數據在評價程式時不能使用。在評價程式時使用測試數據(樣本外)非常重要。

如果在先行走勢法中收集的樣本外數據(綠色)具有優勢的話,那麼在今後的實盤操作期間(紅色箭頭)中獲利的可能性也將提高。

樣本外數據(綠色)

2種過度最佳化

最佳化不應用於提高樣本內的表現,而是應該為了找到在樣本外中起到作用的參數。

如果在樣本內最佳化後而發現的參數在樣本外不能發揮作用的話,就沒有任何意義。

2種過度最佳化

對樣本內和樣本外都進行最佳化。

如果對樣本內過度最佳化的話,樣本內的系統將會預測與邏輯毫無相關的價格波動和噪音。

預測不出的價格波動在樣本外當然也不能預測,所以,在樣本內中發現的參數和最適合樣本外的參數之間就會出現較大的差異。

樣本外過度最佳化的原因是什麼。

例如,在做完先行走勢測試後有想到新的策略,然後修改邏輯再一次進行先行走勢測試。

上面有介紹過度最佳化會在歷史數據中多次往返,但是,像這次只是做了2次先行走勢測試,也就是在修改邏輯之前只做了2次測試,然後就根據結果選擇了邏輯。

參數最佳化只是被邏輯最佳化所取代,所以在開發者還沒有意識到的情況下測試數據變為訓練數據。

再舉一個例子。

例如,在開發程式中進行了100次回測。但是,其大部分結果對於開發者來說都不滿意,只有少數結果達到開發者的標準。

這裡假設有1%的概率,一個本來沒有優勢的程式偶然因為歷史數據中的噪音等原因,導致達到了標準。

也就是說,在100次的回測中,大概有1次把沒有優勢的程式誤判斷為有優勢。

就像過度最佳化一樣,因為偶然預測到了不能預測的東西,所以,在實盤中的成績也會出現偏離。

樣本內的過度最佳化對策

樣本內的過度最佳化的難易程度會受到樣本規模大小和程式的複雜性影響。

考察樣本內的過度最佳化對策。

對策1:增大樣本規模

樣本規模(最佳化期間的交易次數)如果太小的話受到噪音的影響就會變大,最佳化的結果就會極端的上下跳動。

噪音的影響會隨著樣本的規模而變小。

樣本規模大的時候沒有什麼問題,樣本規模小的時候需要估計在偶然的情況下也許會出現大幅跳動。

以下的曲線圖中對推定的母體變異數進行反算,可以看出樣本規模越大分散越小,精確度也會隨之上升。

母體變異數進行反算

樣本規模越小為什麼評價指標就會變得越嚴格。

以下計算公式顯示了隨機交易n次的盈利係數(PF)會在95%以內的概率。

計算公式

隨機交易的PF上限是交易次數越多約會小於1.0,而交易次數越少數值將會越大。

以下是關於最佳化後的PF除以隨機交易的PF上限公式的說明。
  • 交易次數越多,數值越傾向於最佳化後的PF
  • 交易次數越少數值越小
  • 隨機交易的PF超過最佳化後的PF時,數值將達到1.0以上
隨機交易的PF

也就是,把PF/PFr作為最佳化的目標函數將會成為一個對策。

對策2:程式不要太複雜

邏輯越複雜,就越有可能對價格波動做出反應,拾取歷史數據中的噪音。

理想的邏輯是對「可以預測的行情」做出反應,對噪音等其他價格波動不作任何反應。

如果程式簡單到連可預測的行情都不能說明的話也不會產生優勢,而過於複雜的話回測也會變得更難。
  • 根據想要做的行情持倉
  • 不要亂加下單過濾
  • 盡量減少需要最佳化的參數
根據以上想法設定邏輯。

過於複雜的程式雖然容易過度最佳化,但是,也並不是說越簡單越好。

一般來說,可預測的行情都是用最小的設置可以解釋,而「為了防止過度最佳化不做最佳化」的選擇卻大部分都是錯誤。

在Art Colins的著作《Market Beaters》中也寫到,有的參數需要透過最佳化才能判斷是否堅固。。

接下來舉例介紹需要最佳化的參數。

有一個簡單的程式就是在「5的倍數日期的8:30買入美元/日元,在8:55(電匯中間價)平倉」。

這是因為日本企業習慣在5的倍數日期支付所產生的現象,這個策略就是針對在於中間價之前容易上漲的反常現象。

重要的是在中間價平掉多頭部位,而下單的8:30這個時間反而不太重要。

如果不把這個程式最佳化的話會怎麼樣。

從過去的價格波動來看,實際上在8:30之前更早的時間就容易上漲,如果不最佳化的話,就會容易錯過這段時間。

在機器學習領域有一個廣為人知的現象,即一個模型過於簡單或訓練不足,導致較大的誤差,稱之為偏誤,相反,一個模式過於複雜或訓練過度,導致較大的誤差,稱之為方差。

偏誤和方差是不能同時存在的關係。

所以,不要過度簡單或複雜,重要的是找到平衡。

偏誤和方差

對策3:根據最佳化結果確認堅固性

在最佳化時也需要關注最好結果以外的數值。

對於只要稍微修改成為最好結果的參數就會導致結果有很大變動的程式,可以稱之為非常脆弱的程式。

相反,對於即便修改一些參數也不會影響結果,怎麼選擇參數都會有良好結果程式,可能會更加堅固。

對於修改一些參數也有穩定結果的程式,即便在實盤中出現變化,也有可能長期穩定盈利。

脆弱的程式因為會拾取一些偶然的噪音,所以結果也會變得非常片面,也就是說有極大可能時過度最佳化。

下圖是脆弱程式的最佳化結果。

良好結果只佔整體的幾個部分。

脆弱程式的最佳化結果

下面時堅固程式的最佳化結果。

可以看出,整體上都處於良好結果。

堅固程式的最佳化結果

對策4:不選擇最好結果

默默地觀察整個最佳化結果,可以看出是一個山形。

最好結果並不意味著時最優的參數,在山的頂峰附近才是最優的參數。

最佳化結果

當參數連續變化時,山形趨勢逐漸顯示出適合於「可預測的交易機會」。

這裡的微小變化是因為拾取了噪音的影響,所以,明顯突出於頂部的地方有可能是過度最佳化。

重要的是選擇山頂附近的參數,忽略微小的變化。

樣本內的評價

如果可以在樣本內防止過度最佳化的話,樣本內的最優參數和樣本外的最優參數大概是一致的。

樣本外的驗證數據收集完後,可以對樣本外的週期參數進行隨機變化。

透過確認樣本內的最優參數在隨機結果優秀成績的百分比,可以評價最佳化是否成功。

在隨機結果優秀成績的百分比越高,過度最佳化的可能性越低。

樣本外的過度最佳化對策

樣本外的過度最佳化原因在上面已有講過。

樣本外決不允許在歷史數據之間來回往來。

應該注意在歷史數據之間往來的行為除了最佳化以外,還包含對邏輯和交易品種等的改變。

即使是用於實盤的一次性樣本外數據,也有可能意外融入樣本外週期的噪音,表現出超出其真正的潛力。

如果做了100個沒有優勢的程式,也許會有一個偶然超常發揮,但是,這個是不可複製的。

關於樣本噪音

下圖是先行走勢法和沒有進行任何最佳化的單一回測相比較。

先行走勢法

先行走勢法和單一回測相比較,先行走勢的樣本外週期會更短一些。

在樣本內的說明中有介紹到樣本規模越大越不容易出現過度最佳化,對於樣本外也是如此。

正如說明的那樣,因為有一些參數需要最佳化來調查特徵,而且還有測試程式穩健性的目的,所以完全沒有最佳化的單一測試並不是一個好主意。

在最佳化的同時增加樣本外週期的一種方法就是K拆交叉驗證。

K拆交叉驗證

這個方法與先行趨勢法相比,可以增大樣本內和樣本外的樣本規模。

不過,這個方法也有缺點。

先行趨勢法中的樣本外週期和樣本內週期的時間序列都很真實,而K拆交叉驗證是用比樣本外週期更接近當前幾年的數據進行最佳化。

因為使用未來的數據,所以需要注意不要把不知道的信息洩露到樣本外週期。

關於回測途徑

以上所述的先行趨勢法和K拆交叉驗證都有一個相同的缺點,就是只能驗證一條回測途徑。

下面介紹關於這個問題的解決方法,組合分割交叉驗證(CPCV)。

下圖顯示CPCV可以生成多條回測途徑。

多條回測途徑

這個圖雖然只生成了5個回測途徑,如果交易頻度足夠高的話,可以生成幾百幾千個回測途徑。

多次驗證數據的不同之處在於其訓練的的時期,其中也有一些觸及上限和下限的結果混合在一起。

先行趨勢法和K拆交叉驗證的驗證數據只有一個,所以,觸及上限和下限也注意不到。

下面舉例介紹。

使用先行趨勢法進行的一組4年最佳化和1年測試的結果被認為有優勢。

用相同程式再次進行一組5年最佳化和1年測試的回測結果卻沒有優勢。

在第1次和第2次的回測中只是稍微修改了先行趨勢法的設置,但是,結果卻大有不同,就會擔心程式是否穩健。

由於先行趨勢法和K拆交叉驗證的缺點就是只能生成1個回測途徑,所以,即便出現這種問題也注意不到。

如果要用夏普比率來評價的話,先行趨勢法是基於單一的夏普比率,而CPCV卻可以得到多個夏普比率的分佈。

關於洩露

在回測的測試期間中,不應該給程式提供當時還不知道的信息。

2022年美元/日元的匯率大幅上漲。

如果開發者已經知道這個信息,設定為「在2022年積極買入美元/日元」的話,回測結果雖然很好,但是,對於在2022年做測試的程式來說是還不知道的信息。

把獲取還不知道的信息稱之為洩露。

樣本外測試分為訓練數據和測試數據,在進行回測時,如果在訓練數據和測試數據之間沒有空隙的話,就有可能出現洩露。

這是因為如果是預測一週之後的程式的話,最多會有一週的數據有可能會與測試數據重疊。

測試數據重疊

這種空出重疊期的措施被稱為淨化,這也是CPCV(組合分割交叉驗證)的重要技術。

除了淨化以外,對歷史數據追溯計算的技術指標等也會成為洩露的原因。

例如,使用1個月的移動平均線的話,需要空出1個月的時間。

這個被稱為禁令。

禁令

如果在先行趨勢法或CPCV中進行的樣本外測試的次數,也就是訓練數據和測試數據的接觸越多成績越好的話,有可能出現了洩露。

[faq slug="faq_ea89"]

將EA自動程式交易應用於外匯與差價合約交易中

EA

我們以圖文形式詳細介紹有關EA自動程式交易的基本知識,以及在MT4/MT5平台上的安裝、參數設定方法、編碼等等內容。另外,對持有VEXI帳戶的客戶,還可以免費使用我們的獨有EA與指標工具。

]]>
歷史數據的走勢測試 樣本外數據(綠色) 2種過度最佳化 母體變異數進行反算 計算公式 隨機交易的PF 偏誤和方差 脆弱程式的最佳化結果 堅固程式的最佳化結果 最佳化結果 先行走勢法 K拆交叉驗證 多條回測途徑 測試數據重疊 禁令 EA
使用實際源碼介紹如何製作RSI的EA(自動交易) https://www.vexifx.com/bvi-ft/lab-education/ea_trading/relative_strength_index/ Thu, 06 Jul 2023 00:20:43 +0000 https://www.vexifx.com/bvi-ft/lab-education/?post_type=ea_trading&p=34946 RSI的EA(自動交易)透過實際源碼製作說明

什麼是RSI?

RSI是「Relative Strength Index」的簡稱,可以翻譯為「相對強弱指數」。

計算公式為「一定週期內價格上漲幅度總計」除以「一定週期內價格上漲幅度和價格下跌幅度總計」,可以根據得出的數值判斷市場是否超買超賣。

RSI

從圖表的形態和RSI的形態可以看出,RSI的走勢和圖表的走勢基本相同。

RSI是以圖表的信息為基礎進行計算,所以圖表動的話RSI也會跟著動。

但是,並不會預測未來走勢,還請多加注意。

RSI的優勢是,可以0至100之間顯示圖表的價格波動。

因為數值只限於在0至100之間,所以可以判斷為「RSI低於20為超賣」、「RSI超過80為超買」,也是一種很容易編寫到程式中的指標。

關於RSI的詳細內容請參考以下文章。

>介紹RSI的基本解讀、使用方法以及交易策略

EA說明

首先介紹關於製作的EA內容。

在這裡整理好內容的話,有助於提高程式的質量。

下單條件

RSI低於超賣線後下多單

RSI高於超買線後下空單

平倉條件

根據停利價格和停損價格平倉

其他條件

Copyright設置為「VEXI」

透過滑點和點差限制下單數量

設置為只能持有1個部位

可以修改Magic Number和手數

製作EA

程式按照「前置處理」「領域」「函數(OnInit)」「函數(OnInit以外)」的順序進行介紹。

另外,因為文章是日文翻譯內容,所以請參考圖片上對應的中文。

プリプロセッサ:前置處理

フィールド:領域

関数:函數

函數

前置處理

#property copyright " Copyright(C) 2023, VEXI "
#property link "https://www.mql5.com"
#property version "1.00"
#property strict
在默認的前置處理中,把copyright的地方修改為「Copyright(C) 2023, VEXI」。

這樣,當用戶把EA放到圖表是就可以清楚的知道版權屬於誰。

版權
TIPS版權:
編寫Copyright除了明確誰是版權持有人以外,還有「明確版權發行年份」的目的。

另外,正確的Copyright圖標是「©」,但是,由於在MT4中「©」不能明確顯示,所以會用「Copyright(c)」代用。

領域

input int MAGICMA = 23498721; // Magic Number
input double Lots =0.01; // 1手為10萬貨幣
input int Slippage = 4; // 限制下單滑點
input double MaxSpread = 5; // 限制下單點差
input double TakeProfit = 10.0; // 停利點數(pips)
input double LossCut = 20.0; // 停損點數(pips)
input int RSIPeriod=14; // 週期
input ENUM_APPLIED_PRICE RSIAppliedPrice = PRICE_CLOSE; // 價格來源
input int UpLine = 70; // 上線
input int DownLine = 30; // 下線

double dSpread;
這次的RSI的基本參數為「週期」「價格來源」「上線」「下線」。

當價格RSI高於設定的「上線」數值時將會下空單,當低於設定的「下線」時將會下多單。

另外,還添加了停利和停損用的參數「TakeProfit」和「LossCut」。

為了用戶使用方便,設定為用pips設置停利和停損。

OnInit函數

int OnInit()
{
return(INIT_SUCCEEDED);
}
OnInit函數與上次一樣,不需要另作說明。

OnTick函數

void OnTick()
{
dSpread = (Ask - Bid) / (Point * 10);
if(CalculateCurrentOrders()==0 && dSpread < MaxSpread) CheckForOpen();
}
OnTick函數也與上次一樣。

使用CalculateCurrentOrders函數計算現在未平倉的部位數量,當部位數量為0,且點差低於在參數中設定的點數時,會使用CheckForOpen函數進行下單。

這樣,把「計算部位的函數」和「進行下單的函數」分開使用的話,可以節省更多時間,也可以讓代碼更加簡單。

CheckForOpen函數

void CheckForOpen()
{
int res;
double RSI = iRSI(Symbol(), 0, RSIPeriod, RSIAppliedPrice, 1);

if(RSI < DownLine)
{
res=OrderSend(Symbol(), OP_BUY, Lots, Ask, Slippage, Bid - LossCut * Point * 10, Ask + TakeProfit * Point * 10,"", MAGICMA, 0, Red);
}
if(RSI > UpLine)
{
res=OrderSend(Symbol(), OP_SELL, Lots, Bid, Slippage, Ask + LossCut * Point * 10, Bid - TakeProfit * Point * 10, "", MAGICMA, 0, Blue);//
}
}
使用CheckForOpen函數,當RSI數值低於參數中所設定「下線」時就會下多單,當高於「上線」是就會下空單。

首先將iRSI函數存儲至double型的變數RSI中。

然後在後面加入if語句確認超買超賣,進行反向交易。

OrderSend函數的第6參數和第7參數可以分別指定為停利價格和停損價格。

下圖為換做MT4下單介面時的示意圖,日文對應的中文如下。

買いエントリー場合:買入進場時

利確価格:停利價格

損切価格:停損價格

OrderSend函數

完整源碼

#property copyright "Copyright(C) 2023, VEXI"
#property link "https://www.mql5.com"
#property version "1.00"
#property strict

input int MAGICMA = 23498721; // Magic Number
input double Lots =0.01; // 1手為10萬貨幣
input int Slippage = 4; // 限制下單滑點
input double MaxSpread = 5; // 限制下單點差
input double TakeProfit = 10.0; // 停利點數(pips)
input double LossCut = 20.0; // 停損點數(pips)
input int RSIPeriod=14; // 週期
input ENUM_APPLIED_PRICE RSIAppliedPrice = PRICE_CLOSE; // 價格來源
input int UpLine = 70; // 上線
input int DownLine = 30; // 下線

double dSpread;

int OnInit()
{
return(INIT_SUCCEEDED);
}
void OnTick()
{
dSpread = (Ask - Bid) / (Point * 10);
if(CalculateCurrentOrders()==0 && dSpread < MaxSpread) CheckForOpen();//如果沒有部位的話可以建新部位

}
void CheckForOpen()
{
int res;
double RSI = iRSI(Symbol(), 0, RSIPeriod, RSIAppliedPrice, 1);

if(RSI < DownLine)
{
res=OrderSend(Symbol(), OP_BUY, Lots, Ask, Slippage, Bid - LossCut * dPoint, Ask + TakeProfit * dPoint,"", MAGICMA, 0, Red);
}
if(RSI > UpLine)
{
res=OrderSend(Symbol(), OP_SELL, Lots, Bid, Slippage, Ask + LossCut * dPoint, Bid - TakeProfit * dPoint, "", MAGICMA, 0, Blue);
}
}

int CalculateCurrentOrders()
{
int positions = 0;
for(int i=0;i {
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;
if(OrderSymbol()==Symbol() && OrderMagicNumber()==MAGICMA)
{
positions++;
}
}
return positions;
}
[faq slug="faq_ea88"]

將EA自動程式交易應用於外匯與差價合約交易中

EA

我們以圖文形式詳細介紹有關EA自動程式交易的基本知識,以及在MT4/MT5平台上的安裝、參數設定方法、編碼等等內容。另外,對持有VEXI帳戶的客戶,還可以免費使用我們的獨有EA與指標工具。

]]>
RSI 函數 版權 OrderSend函數 EA
活用蒙地卡羅法並透過回測估算未來回落的方法 https://www.vexifx.com/bvi-ft/lab-education/ea_trading/beginner-drawdown_assumption/ Thu, 06 Apr 2023 00:34:34 +0000 https://www.vexifx.com/bvi-ft/lab-education/?post_type=ea_trading&p=34242 活用蒙地卡羅法並透過回測估算未來回落的方法
由於回測中的最大回落是基於過去數據的盈虧得出,因此難以作為估算未來回落幅度的依據。

透過單次的回測,並無法判斷最大回落將會因為偶然因素而出現較大或較小的結果。

從回測的傾向來估算往後發生的回落極為重要,而非只於事後再透過回測來說明已經明顯形成的回落。

回落進行說明

在本篇文章中,將說明採用蒙地卡羅法來考察「未來必須容忍多大幅度的回落」的方法。

只要得知必須容忍的回落幅度,即可在未來發生回落的時候,判斷應該持續進行或停止運用系統。

什麼是蒙地卡羅法

在系統損益中的蒙地卡羅法,是利用亂數假設一個出現各種盈虧的系統場景,再以此來進行系統評估以及風險管理的手法。

為了掌握整體的概念,首先將簡單說明蒙地卡羅法的步驟。

先準備好回測以及即時前瞻抽樣得出的盈虧資料。

從準備好的盈虧資料當中,隨機抽樣取出n次的交易盈虧。
在此必須注意,隨機抽樣並非隨機排序或是不重複抽樣,而是採用重複抽樣(允許重複抽出)。

可將此隨機抽樣得到的交易次數n製成新的損益資料。

藉由重複進行這樣的過程,此隨機抽樣得出的交易次數n,將會產生無數個盈虧資料。
以下將舉例說明。

下圖為100次交易的隨機抽樣。

100次交易的隨機抽樣

其次為重複1000次的100次交易隨機抽樣示意圖。

100次交易隨機抽樣示意圖

從已經實現的盈虧資料當中,可得出複數(在此範例中為1000)的評鑑指標 (獲利因子、最大回落等等)。

蒙地卡羅法的目的

已經實現的損益資料並非來自於回測或即時前瞻的路徑。

不同路徑的盈虧資料可能會偏於正面,亦可能偏於反面。
當實際運用於系統上時,有可能時運不佳而出現偏向反面的結果,為了避免因為這樣的狀況導致預料之外的損失,便可事先利用蒙地卡羅法來估算「時運不佳而偏向反面的結果」。

由於蒙地卡羅法是利用隨機採樣的結果加以評估,並獨立進行系統盈虧的假設,因此可能不適用於具有高度相依性的系統。

關於盈虧的相依性

以下將考察獨立測試的假設不適用於模擬回落的理由。

獨立測試可視為投擲硬幣。
無論投擲硬幣的結果已經連續出現了多少次的正面或反面,下一次的結果依然會是50%的機率。
獨立測試便是如此,下一次的結果不會受到過去的結果所影響,機率與期望值都會維持固定不變。

而相依測試與獨立測試有所不同,過去的結果將會影響下一次的機率與期望值。

以下為具有高度相依性的損益示意圖。

損益示意圖

與勝負隨機發生的損益傾向(獨立測試)相比,正向的高度相依性容易造成較大的最大回落,而反向的高度相依性則會帶來較小的最大回落。

也就是說,若使用獨立測試的蒙地卡羅法,在估算具有高度正向相依性的系統最大回落時,將會出現過小的評估結果。

同樣地,當估算具有高度反向相依性的系統時,將會出現過大的評估結果。

調查有無相依性的連檢定

驗證有無相依性的方法眾多,以下將針對連檢定加以說明。

連檢定可調查數列「有多接近獨立測試」,並以數值加以顯示。

連檢定常用來查詢大於中間值的數值將會連續抑或交互出現。

若將連檢定用於交易中的損益,將可得知結果會大於0還是小於0,意即能夠判斷交易的結果會成功還是失敗。

連續成功或失敗的交易可統稱為連,並如以下所示加以計算。

交易成敗

正向相依性越高則連的數量越少,反向相依性越高則連的數量越多。

當進行獨立測試時,可以透過以下公式得出連的平均數與變異數,再從計算出的分數Z來判斷「應該屬於獨立測試的範疇,還是當作相依測試」。

平均數與變異數

在此範例公式的數值中,分數Z若比±1.96更接近0便屬於獨立測試,高於+1.96則代表具有高度的反向相依性,反之低於-1.96就代表具有高度的正向相依性。
1.96這個數值是基於統計學的標準常態分布表所得出。

雖然可以透過連檢定來調查是否具有相依性,但仍難以藉此來精準判斷是相依測試或獨立測試。

此處相當重要的一點,即是模擬蒙地卡羅法中分數Z為0時的損益。

針對分數Z過低的系統,若使用蒙地卡羅法來估算最大回落,便會得到過小的評估結果,而針對分數Z過高的系統,若使用蒙地卡羅法來估算最大回落,則會得到過大的評估結果。

透過連檢定所得出的分數Z,將可用於判斷蒙地卡羅法估算出的最大回落「有多少參考價值」。

模擬最大回落

使用實際的資料來進行蒙地卡羅法,並將得出的複數最大回落以直方圖來表示。

此處將單次抽樣用於100次交易,並進行5000次的蒙地卡羅法測試。

也就是針對作為估算目標的系統,從回測與即時前瞻測試中隨機取出100次交易,並製成新的盈虧路徑,再將其重複5000次來產生5000條盈虧路徑。

左側圖表即為產生的5000條盈虧曲線。

右側則是分別計算5000條盈虧路徑的最大回落並製成直方圖。

直方圖

將盈虧各自獨立作為前提,產生的5000條盈虧路徑可視為「若盈虧資料的特徵不變,未來將可能出現的盈虧路徑」。
在原本就具有優勢的狀況下,可將蒙地卡羅法的結果歸納為「只要能持續保持該優勢,未來將可能形成這樣的局勢」。

若將得出的5000個最大回落合併分割成10個數據分組,將能目測判斷可能發生的最大回落幅度。

10個數據分組

以下來確認數據分組的資料內容。

數據分組資料

針對最可能發生的第2個合併項目,可以見到實際測出的機率數值為38.04%、最大回落的幅度則是16431〜27073。
當運用此系統進行100次交易時,就應該設想可能會發生此幅度的最大回落。

接下來,要考量最大回落達到容忍度上限的的局勢。

本次將95%作為必須容忍的發生機率。
以下來關注同表格的第5個項目。
由於第5個項目的累積(%)為96.46,因此可判斷絕大多數的最大回落都止步於第5個項目。

96.46%概率

因為第6個項目之後的最大回落發生機率低於5%,故若將其判斷為異常狀態,則第5個項目為止的最大回落幅度即為必須容忍的範圍。

也就是說,最大回落到58998為止皆可以接受,一旦大於此數值就可視為異常狀態。

總結

最後再回顧一次,判斷蒙地卡羅法時「前提為使用獨立測試,且驗證資料的優勢保持不變」,只要失去此前提便應視為異常狀態(當最大回落超過容忍範圍)。
如果是基於具有優勢的驗證資料來運用系統,那麼一旦失去此前提就應該停止使用。

[faq slug="faq_ea87"]

將EA自動程式交易應用於外匯與差價合約交易中

EA

我們以圖文形式詳細介紹有關EA自動程式交易的基本知識,以及在MT4/MT5平台上的安裝、參數設定方法、編碼等等內容。另外,對持有VEXI帳戶的客戶,還可以免費使用我們的獨有EA與指標工具。

]]>
回落進行說明 100次交易的隨機抽樣 100次交易隨機抽樣示意圖 損益示意圖 交易成敗 平均數與變異數 直方圖 10個數據分組 數據分組資料 96.46%概率 EA
什麼是顯著水準?判斷回測與交易結果優勢的分析方法 https://www.vexifx.com/bvi-ft/lab-education/ea_trading/win_no_coincidence_proof-all/ Mon, 27 Feb 2023 03:59:51 +0000 https://www.vexifx.com/bvi-ft/lab-education/?post_type=ea_trading&p=34015 什麼是顯著水準?判斷回測與交易結果優勢的分析方法
統計學有一術語為「顯著水準」。

在統計學中,當一件事情發生的機率低到難以被判斷為偶然,此機率便被稱為顯著水準。

此機率可作為判斷一個事件的意義以及是否為偶然發生的標準。

藉由系統回測與實際交易的結果,雖然能夠得知是否成功或是趨於穩定,但卻無法判斷該結果是偶然發生、還是因為本身具有優勢而產生。

但是,如果能夠區分該結果是「偶然出現的結果」還是「因為具有優勢而產生的結果」,將可活用於系統的判斷。

本篇文章將詳細說明判斷系統優勢的分析方法。

1.將隨機的交易結果作為比較對象

為了判斷系統是否具有優勢,必須先將沒有優勢的交易結果作為比較對象加以考察。

接著將虛構的隨機交易系統假設為沒有優勢的系統。
隨機交易的定義如以下所示。

此處暫不考慮點差、滑價等交易成本。
    1.長期的期望值收斂於±0。
    2.獲利因子(PF)收斂於1.0。
    3.平均收益與平均虧損收斂於相同數值。
若將n作為隨機交易的交易次數,即可成立以下的公式。

公式

由於勝負收斂於相同的數值,因此可無視盈虧(損益)的額度,而將隨機交易分為成功或失敗兩個種類。

因為共有兩種結果,所以使用二項式分布。
以機率p、測試次數n作為條件,下方即是二項式分布的變異數公式。

變異數公式

若機率p符合隨機交易的成功機率(=失敗機率),便會形成以下的標準差。

標準差

若把隨機交易結果產生的成功交易次數依照常態分布,則成功的交易次數將落在95%的信賴區間中,並可歸納至此公式。

盈利交易次數

以下來確認PF的計算公式。

PF的計算公式

由於此處的公式皆可算出PF,因此會得出相同的計算結果。

一開始已經先決定了隨機交易結果的定義為「平均收益與平均損失收斂於相同數值」。

因此能依照「平均收益=平均虧損」的概念來改變公式。

平均收益=平均虧損

根據隨機的交易結果,先前已得出成功交易次數落在95%範圍內的計算公式,此處將加以應用,顯示出執行了n次的隨機交易結果PF落在95%的範圍內。

PF落在95%的範圍內

用於判斷系統是否具有優勢的PF,應該要優於透過此隨機交易結果所歸納出的95%範圍。

2.關於初始交易分析

初始交易分析的計算概念與技術性指標的移動平均線相同,是任意取樣自交易次數加以分析的手法。

以下將舉例說明。

假設擁有1000次交易系統的盈虧資料。

從一開始的第1次交易到第100次交易之間,取出共計100次交易,並製作成新的盈虧資料。

100次交易

其次,從第2次交易到第101次交易之間,取出共計100次交易,再度製作成新的盈虧資料。

盈虧資料

請注意第一次與第二次取出的盈虧資料之間,取樣的範圍只有1次交易的變化。

以此模式來反覆替換取出的盈虧資料直到最後。

盈虧資料

藉由分別取出100次的交易,即可計算每一份盈虧資料的PF等評鑑指標。

若使用1000次的交易資料,再分別取出100次的交易來進行初始交易分析,則共計會得到901份盈虧資料,並能夠計算每一份盈虧資料的PF等評鑑指標。

透過這樣的方式,即可了解PF將如何隨著時間產生變化等資訊。

PF圖表
此為實際透過初始交易分析計算得出的PF圖表。

此範例中的交易次數為282次,若採用常態計算得出整體PF為1.3的盈虧資料,並分別取出100次的交易來進行初始交易分析,則初始交易分析的測試次數將是183次。

整體PF 1.3
圖表中的綠線代表以常態計算得出的整體PF 1.3。

雖然常態的PF為1.3,但由於PF是使用分別取出的100次交易資料計算得出,因此依照優勢與劣勢等不同時期,將會出現大約1.7~1.1的波動幅度,此點能夠從圖表判讀得知。

藉由上述的初始交易分析,能夠顯示自任意交易次數計算得出的評鑑指標(此處為PF)走勢。

3.比較PF的走勢與隨機交易

當分別取出100次交易資料來進行初始交易分析時,將前述可供計算的隨機交易結果作為比較的對象。

由於各交易次數為100次,因此將100代入為n。

PF為0.67~1.49之間

也就是說,100次隨機交易結果的PF為0.67~1.49之間,機率可歸納為95%。

將此計算結果與先前透過初始交易分析製成的圖表重疊顯示。

粉色區域上限為1.49

圖表內的粉色區域上限為1.49、下限為0.67,顯示出「100次隨機交易結果的95%機率都在PF的範圍中」。

也就是說,在此粉色的區域中,100次隨機交易結果偶然跳離的比例約為2.5%。

如欲判斷此PF走勢是否會優於隨機的交易結果,第一個關鍵便是常態計算得出的整體PF高於1.0。

第二個需要注意的重點,則是跳離粉色區域上限的比例超過了2.5%。

PF走勢與隨機交易結果比較

如畫面所示,可以確認已經符合了兩個判斷的標準。

此外,還有一個重點需要考量。

雖然先前說明了隨機交易結果偶然跳離粉色區域的比例約為2.5%,但若考量到此比例的波動幅度,則判斷標準將變得更加嚴苛。

由於183次測試在粉色區域偶然跳離的機率為2.5%,因此可利用二項式分布計算是否會跳離的期望值與變異數。

期望值與變異數

由此可見,若初始交易分析的結果跳離粉色區域上限的比例高於4.76%,則即使隨機交易結果的波動幅度較大,也仍然能夠判斷為具有優勢。

在本次的範例中,由於超過粉色區域上限範圍的比例為20.77%,因此可輕易判斷為符合條件。

透過上述的方法,能夠得知系統具有優勢的可能性極高。

總結

本次文章將回測以及實際交易的結果與隨機交易的結果互相比較,並說明了如何利用判斷標準來確認是否具有優勢。

在使用回測資料進行此驗證時,必須以該回測資料並未經過曲線擬合為前提,一旦經過了曲線擬合便可能導致過度估算,此點需多加留意。

雖然對於即時交易能夠有所助益,但是在結果不如預期優秀的狀況下,投資人亦可將此驗證方式作為停止系統運作的判斷標準。

[faq slug="faq_ea86"]

將EA自動程式交易應用於外匯與差價合約交易中

EA

我們以圖文形式詳細介紹有關EA自動程式交易的基本知識,以及在MT4/MT5平台上的安裝、參數設定方法、編碼等等內容。另外,對持有VEXI帳戶的客戶,還可以免費使用我們的獨有EA與指標工具。

]]>
公式 變異數公式 標準差 盈利交易次數 PF的計算公式 平均收益=平均虧損 PF落在95%的範圍內 100次交易 盈虧資料 盈虧資料 PF圖表 整體PF 1.3 PF為0.67~1.49之間 粉色區域上限為1.49 PF走勢與隨機交易結果比較 期望值與變異數 EA