Yêu cầu ký quỹ
Trong số những thông tin quan trọng nhất về một công cụ tài chính đối với nhà giao dịch là số tiền cần thiết để mở một vị thế. Nếu không biết cần bao nhiêu tiền để mua hoặc bán một số lượng lot nhất định, sẽ không thể triển khai hệ thống quản lý tiền trong Expert Advisor và kiểm soát số dư tài khoản.
Vì MetaTrader 5 được sử dụng để giao dịch nhiều công cụ khác nhau (tiền tệ, hàng hóa, cổ phiếu, trái phiếu, quyền chọn và hợp đồng tương lai), nguyên tắc tính toán ký quỹ khác nhau đáng kể. Tài liệu cung cấp chi tiết, đặc biệt cho Forex và hợp đồng tương lai cũng như sàn giao dịch.
Một số thuộc tính của API MQL5 cho phép xác định loại thị trường và phương pháp tính toán ký quỹ cho một công cụ cụ thể.
Nhìn trước, hãy nói rằng với một tổ hợp các tham số như loại hoạt động giao dịch, công cụ, khối lượng và giá, MQL5 cho phép tính toán ký quỹ bằng hàm OrderCalcMargin
. Đây là phương pháp đơn giản nhất, nhưng nó có một hạn chế đáng kể: hàm không tính đến các vị thế đang mở và lệnh chờ hiện tại. Điều này, đặc biệt, bỏ qua các điều chỉnh có thể có đối với khối lượng chồng lấn khi các vị thế đối lập được phép trên tài khoản.
Do đó, để có được chi tiết về số tiền tài khoản hiện đang được sử dụng làm ký quỹ cho các vị thế và lệnh đang mở, một chương trình MQL có thể cần phân tích các thuộc tính sau và tính toán bằng công thức. Hơn nữa, hàm OrderCalcMargin
bị cấm sử dụng trong các chỉ báo. Bạn có thể ước tính trước ký quỹ tự do sau khi giao dịch đề xuất hoàn tất bằng OrderCheck
.
Định danh | Mô tả |
---|---|
SYMBOL_TRADE_CALC_MODE | Phương pháp tính toán ký quỹ và lợi nhuận (xem ENUM_SYMBOL_CALC_MODE) |
SYMBOL_MARGIN_HEDGED_USE_LEG | Cờ boolean để bật (true) hoặc tắt (false) chế độ tính toán ký quỹ hedging cho vị thế lớn nhất trong các vị thế chồng lấn (mua và bán) |
SYMBOL_MARGIN_INITIAL | Ký quỹ ban đầu cho một công cụ sàn giao dịch |
SYMBOL_MARGIN_MAINTENANCE | Ký quỹ duy trì cho một công cụ sàn giao dịch |
SYMBOL_MARGIN_HEDGED | Kích thước hợp đồng hoặc ký quỹ cho một lot của các vị thế được bao phủ (các vị thế đối lập cho một ký hiệu) |
Hai thuộc tính đầu tiên thuộc liệt kê ENUM_SYMBOL_INFO_INTEGER
, và ba thuộc tính cuối thuộc ENUM_SYMBOL_INFO_DOUBLE
, chúng có thể được đọc lần lượt bằng các hàm SymbolInfoInteger
và SymbolInfoDouble
.
Công thức tính toán ký quỹ cụ thể phụ thuộc vào thuộc tính SYMBOL_TRADE_CALC_MODE
và được hiển thị trong bảng dưới đây. Thông tin đầy đủ hơn có thể được tìm thấy trong tài liệu MQL5.
Lưu ý rằng ký quỹ ban đầu và duy trì không được sử dụng cho các công cụ Forex, và các thuộc tính này luôn bằng 0 đối với chúng.
Ký quỹ ban đầu cho biết số tiền bảo đảm yêu cầu trong tiền tệ ký quỹ để mở một vị thế với khối lượng một lot. Nó được sử dụng khi kiểm tra tính đủ của tiền của khách hàng trước khi vào thị trường. Để có được số tiền ký quỹ cuối cùng bị tính phí tùy thuộc vào loại và hướng của lệnh, hãy kiểm tra tỷ lệ ký quỹ bằng hàm SymbolInfoMarginRate
. Do đó, nhà môi giới có thể đặt đòn bẩy hoặc chiết khấu riêng cho từng công cụ.
Ký quỹ duy trì cho biết giá trị tối thiểu của số tiền trong tiền tệ ký quỹ của công cụ để duy trì một vị thế mở với một lot. Nó được sử dụng khi kiểm tra tính đủ của tiền của khách hàng khi trạng thái tài khoản (điều kiện giao dịch) thay đổi. Nếu mức tiền giảm xuống dưới số tiền ký quỹ duy trì của tất cả các vị thế, nhà môi giới sẽ bắt đầu đóng chúng một cách cưỡng chế.
Nếu thuộc tính ký quỹ duy trì bằng 0, thì ký quỹ ban đầu được sử dụng. Như trong trường hợp ký quỹ ban đầu, để có được số tiền ký quỹ cuối cùng bị tính phí tùy thuộc vào loại và hướng, bạn nên kiểm tra tỷ lệ ký quỹ bằng hàm SymbolInfoMarginRate
.
Các vị thế hedging, tức là các vị thế đa hướng cho cùng một ký hiệu, chỉ có thể tồn tại trên các tài khoản giao dịch hedging. Rõ ràng, việc tính toán ký quỹ hedging cùng với các thuộc tính SYMBOL_MARGIN_HEDGED_USE_LEG
, SYMBOL_MARGIN_HEDGED
chỉ có ý nghĩa trên các tài khoản như vậy. Ký quỹ hedging được áp dụng cho khối lượng được bao phủ.
Nhà môi giới có thể chọn cho mỗi công cụ một trong hai phương pháp hiện có để tính toán ký quỹ cho các vị thế được bao phủ:
- Tính toán cơ bản được áp dụng khi chế độ tính toán phía dài nhất bị tắt, tức là thuộc tính
SYMBOL_MARGIN_HEDGED_USE_LEG
bằngfalse
. Trong trường hợp này, ký quỹ gồm ba thành phần: ký quỹ cho khối lượng không được bao phủ của vị thế hiện có, ký quỹ cho khối lượng được bao phủ (nếu có các vị thế đối lập và thuộc tínhSYMBOL_MARGIN_HEDGED
khác không), ký quỹ cho các lệnh chờ. Nếu ký quỹ ban đầu được đặt cho công cụ (thuộc tínhSYMBOL_MARGIN_INITIAL
khác không), thì ký quỹ hedging được chỉ định dưới dạng giá trị tuyệt đối (bằng tiền). Nếu ký quỹ ban đầu không được đặt (bằng 0), thìSYMBOL_MARGIN_HEDGED
chỉ định kích thước hợp đồng sẽ được sử dụng khi tính toán ký quỹ theo công thức tương ứng với loại công cụ giao dịch (SYMBOL_TRADE_CALC_MODE
). - Tính toán vị thế cao nhất được áp dụng khi thuộc tính
SYMBOL_MARGIN_HEDGED_USE_LEG
bằngtrue
. Giá trị củaSYMBOL_MARGIN_HEDGED
bị bỏ qua trong trường hợp này. Thay vào đó, khối lượng của tất cả các vị thế ngắn và dài trên công cụ được tính toán, và giá mở trung bình có trọng số được tính cho mỗi phía. Tiếp theo, sử dụng các công thức tương ứng với loại công cụ (SYMBOL_TRADE_CALC_MODE
), ký quỹ cho phía ngắn và phía dài được tính toán. Giá trị lớn nhất được sử dụng làm giá trị cuối cùng.
Bảng sau liệt kê các phần tử của ENUM_SYMBOL_CALC_MODE
và các phương pháp tính toán ký quỹ tương ứng. Thuộc tính này (SYMBOL_TRADE_CALC_MODE
) cũng chịu trách nhiệm tính toán lợi nhuận/thua lỗ của một vị thế, nhưng chúng ta sẽ xem xét khía cạnh này sau, trong chương về các hàm giao dịch MQL5.
Định danh | Công thức |
---|---|
SYMBOL_CALC_MODE_FOREX Forex | Lots * ContractSize * MarginRate / Leverage |
SYMBOL_CALC_MODE_FOREX_NO_LEVERAGE Forex không đòn bẩy | Lots * ContractSize * MarginRate |
SYMBOL_CALC_MODE_CFD CFD | Lots * ContractSize * MarketPrice * MarginRate |
SYMBOL_CALC_MODE_CFDLEVERAGE CFD có đòn bẩy | Lots * ContractSize * MarketPrice * MarginRate / Leverage |
SYMBOL_CALC_MODE_CFDINDEX CFD trên chỉ số | Lots * ContractSize * MarketPrice * TickPrice / TickSize * MarginRate |
SYMBOL_CALC_MODE_EXCH_STOCKS Chứng khoán trên sàn giao dịch | Lots * ContractSize * LastPrice * MarginRate |
SYMBOL_CALC_MODE_EXCH_STOCKS_MOEX Chứng khoán trên MOEX | Lots * ContractSize * LastPrice * MarginRate |
SYMBOL_CALC_MODE_FUTURES Hợp đồng tương lai | Lots * InitialMargin * MarginRate |
SYMBOL_CALC_MODE_EXCH_FUTURES Hợp đồng tương lai trên sàn giao dịch | Lots * InitialMargin * MarginRatehoặc Lots * MaintenanceMargin * MarginRate |
SYMBOL_CALC_MODE_EXCH_FUTURES_FORTS Hợp đồng tương lai trên FORTS | Lots * InitialMargin * MarginRatehoặc Lots * MaintenanceMargin * MarginRate |
SYMBOL_CALC_MODE_EXCH_BONDS Trái phiếu trên sàn giao dịch | Lots * ContractSize * FaceValue * OpenPrice / 100 |
SYMBOL_CALC_MODE_EXCH_BONDS_MOEX Trái phiếu trên MOEX | Lots * ContractSize * FaceValue * OpenPrice / 100 |
SYMBOL_CALC_MODE_SERV_COLLATERAL | Tài sản không giao dịch được (ký quỹ không áp dụng) |
Các ký hiệu sau được sử dụng trong công thức:
- Lots — khối lượng vị thế hoặc lệnh tính bằng lot (phần của hợp đồng)
- ContractSize — kích thước hợp đồng (một lot,
SYMBOL_TRADE_CONTRACT_SIZE
) - Leverage — đòn bẩy tài khoản giao dịch (
ACCOUNT_LEVERAGE
) - InitialMargin — ký quỹ ban đầu (
SYMBOL_MARGIN_INITIAL
) - MaintenanceMargin — ký quỹ duy trì (
SYMBOL_MARGIN_MAINTENANCE
) - TickPrice — giá tick (
SYMBOL_TRADE_TICK_VALUE
) - TickSize — kích thước tick (
SYMBOL_TRADE_TICK_SIZE
) - MarketPrice — giá
Bid/Ask
cuối cùng được biết tùy thuộc vào loại giao dịch - LastPrice — giá
Last
cuối cùng được biết - OpenPrice — giá mở trung bình có trọng số của một vị thế hoặc lệnh
- FaceValue — mệnh giá của trái phiếu
- MarginRate — tỷ lệ ký quỹ theo hàm
SymbolInfoMarginRate
, cũng có thể có 2 giá trị khác nhau: cho ký quỹ ban đầu và duy trì
Một cách triển khai thay thế của các phép tính công thức cho hầu hết các loại ký hiệu được đưa ra trong tệp MarginProfitMeter.mqh
(xem phần Ước tính lợi nhuận của một hoạt động giao dịch). Nó cũng có thể được sử dụng trong các chỉ báo.
Hãy đưa ra một vài bình luận về một số chế độ.
Trong bảng trên, chỉ ba công thức hợp đồng tương lai sử dụng ký quỹ ban đầu (SYMBOL_MARGIN_INITIAL
). Tuy nhiên, nếu thuộc tính này có giá trị khác không trong thông số kỹ thuật của bất kỳ ký hiệu nào khác, thì nó xác định ký quỹ.
Một số sàn giao dịch có thể áp đặt các đặc thù riêng của họ vào việc điều chỉnh ký quỹ, chẳng hạn như hệ thống chiết khấu cho FORTS (SYMBOL_CALC_MODE_EXCH_FUTURES_FORTS
). Xem tài liệu MQL5 và nhà môi giới của bạn để biết chi tiết.
Trong chế độ SYMBOL_CALC_MODE_SERV_COLLATERAL
, giá trị của một công cụ được tính vào Tài sản, được cộng vào Vốn chủ sở hữu. Do đó, các vị thế mở trên công cụ như vậy làm tăng số lượng Ký quỹ Tự do và đóng vai trò là tài sản đảm bảo bổ sung cho các vị thế mở trên các công cụ được giao dịch. Giá trị thị trường của một vị thế mở được tính toán dựa trên khối lượng, kích thước hợp đồng, giá thị trường hiện tại và tỷ lệ thanh khoản: Lots * ContractSize * MarketPrice * LiquidityRate
(giá trị sau có thể được lấy dưới dạng thuộc tính SYMBOL_TRADE_LIQUIDITY_RATE
).
Ví dụ về việc làm việc với các thuộc tính liên quan đến ký quỹ, hãy xem xét kịch bản SymbolFilterMarginStats.mq5
. Mục đích của nó sẽ là tính toán thống kê về các phương pháp tính toán ký quỹ trong danh sách các ký hiệu được chọn, cũng như tùy chọn ghi lại các thuộc tính này cho mỗi ký hiệu. Chúng ta sẽ chọn các ký hiệu để phân tích bằng lớp bộ lọc đã biết SymbolFilter
và các điều kiện cho nó được cung cấp từ các biến đầu vào.
#include <MQL5Book/SymbolFilter.mqh>
input bool UseMarketWatch = false;
input bool ShowPerSymbolDetails = false;
input bool ExcludeZeroInitMargin = false;
input bool ExcludeZeroMainMargin = false;
input bool ExcludeZeroHedgeMargin = false;
2
3
4
5
6
7
Theo mặc định, thông tin được yêu cầu cho tất cả các ký hiệu có sẵn. Để giới hạn ngữ cảnh chỉ trong tổng quan thị trường, chúng ta nên đặt UseMarketWatch
thành true
.
Tham số ShowPerSymbolDetails
cho phép bật xuất thông tin chi tiết về mỗi ký hiệu (theo mặc định, tham số là false
, và chỉ thống kê được hiển thị).
Ba tham số cuối cùng nhằm mục đích lọc các ký hiệu theo điều kiện của các giá trị ký quỹ bằng không (ban đầu, duy trì và hedging, tương ứng).
Để thu thập và hiển thị thuận tiện trong nhật ký một tập hợp đầy đủ các thuộc tính cho mỗi ký hiệu (khi ShowPerSymbolDetails
được bật), cấu trúc MarginSettings
được định nghĩa trong mã.
struct MarginSettings
{
string name;
ENUM_SYMBOL_CALC_MODE calcMode;
bool hedgeLeg;
double initial;
double maintenance;
double hedged;
};
2
3
4
5
6
7
8
9
Vì một số thuộc tính là số nguyên (SYMBOL_TRADE_CALC_MODE
, SYMBOL_MARGIN_HEDGED_USE_LEG
), và một số là số thực (SYMBOL_MARGIN_INITIAL
, SYMBOL_MARGIN_MAINTENANCE
, SYMBOL_MARGIN_HEDGED
), chúng sẽ phải được yêu cầu bởi đối tượng bộ lọc riêng lẻ.
Bây giờ hãy chuyển trực tiếp đến mã hoạt động trong OnStart
. Ở đây, như thường lệ, chúng ta định nghĩa đối tượng bộ lọc (f
), mảng đầu ra cho tên ký hiệu (symbols
), và giá trị của các thuộc tính được yêu cầu (flags
, values
). Ngoài chúng, chúng ta thêm một mảng cấu trúc MarginSettings
.
void OnStart()
{
SymbolFilter f; // đối tượng bộ lọc
string symbols[]; // mảng cho tên
long flags[][2]; // mảng cho vector số nguyên
double values[][3]; // mảng cho vector số thực
MarginSettings margins[]; // mảng đầu ra tổng hợp
...
2
3
4
5
6
7
8
Mảng bản đồ stats
đã được giới thiệu để tính toán thống kê với khóa như ENUM_SYMBOL_CALC_MODE
và giá trị số nguyên int
cho số lần mỗi phương pháp được gặp. Ngoài ra, tất cả các trường hợp ký quỹ bằng không và chế độ tính toán được bật trên phía dài hơn nên được ghi lại trong các biến đếm tương ứng.
MapArray<ENUM_SYMBOL_CALC_MODE,int> stats; // bộ đếm cho mỗi phương pháp/chế độ
int hedgeLeg = 0; // và các bộ đếm khác
int zeroInit = 0; // ...
int zeroMaintenance = 0;
int zeroHedged = 0;
...
2
3
4
5
6
Tiếp theo, chúng ta chỉ định các thuộc tính mà chúng ta quan tâm liên quan đến ký quỹ, sẽ được đọc từ cài đặt ký hiệu. Đầu tiên là số nguyên trong mảng ints
và sau đó là số thực trong mảng doubles
.
ENUM_SYMBOL_INFO_INTEGER ints[] =
{
SYMBOL_TRADE_CALC_MODE,
SYMBOL_MARGIN_HEDGED_USE_LEG
};
ENUM_SYMBOL_INFO_DOUBLE doubles[] =
{
SYMBOL_MARGIN_INITIAL,
SYMBOL_MARGIN_MAINTENANCE,
SYMBOL_MARGIN_HEDGED
};
...
2
3
4
5
6
7
8
9
10
11
12
13
Tùy thuộc vào các tham số đầu vào, chúng ta sẽ đặt các điều kiện lọc.
if(ExcludeZeroInitMargin) f.let(SYMBOL_MARGIN_INITIAL, 0, SymbolFilter::IS::GREATER);
if(ExcludeZeroMainMargin) f.let(SYMBOL_MARGIN_MAINTENANCE, 0, SymbolFilter::IS::GREATER);
if(ExcludeZeroHedgeMargin) f.let(SYMBOL_MARGIN_HEDGED, 0, SymbolFilter::IS::GREATER);
...
2
3
4
Bây giờ mọi thứ đã sẵn sàng để chọn các ký hiệu theo điều kiện và lấy thuộc tính của chúng vào các mảng. Chúng ta thực hiện điều này hai lần, riêng biệt cho các thuộc tính số nguyên và số thực.
f.select(UseMarketWatch, ints, symbols, flags);
const int n = ArraySize(symbols);
ArrayResize(symbols, 0, n);
f.select(UseMarketWatch, doubles, symbols, values);
...
2
3
4
5
Một mảng với các ký hiệu phải được đặt về không sau lần áp dụng bộ lọc đầu tiên để tên không bị trùng lặp. Mặc dù có hai truy vấn riêng biệt, thứ tự các phần tử trong tất cả các mảng đầu ra (ints
và doubles
) là giống nhau, vì các điều kiện lọc không thay đổi.
Nếu nhật ký chi tiết được người dùng bật, chúng ta cấp phát bộ nhớ cho mảng cấu trúc margins
.
if(ShowPerSymbolDetails) ArrayResize(margins, n);
Cuối cùng, chúng ta tính toán thống kê bằng cách lặp qua tất cả các phần tử của các mảng kết quả và tùy chọn điền vào mảng cấu trúc.
for(int i = 0; i < n; ++i)
{
stats.inc((ENUM_SYMBOL_CALC_MODE)flags[i].value[0]);
hedgeLeg += (int)flags[i].value[1];
if(values[i].value[0] == 0) zeroInit++;
if(values[i].value[1] == 0) zeroMaintenance++;
if(values[i].value[2] == 0) zeroHedged++;
if(ShowPerSymbolDetails)
{
margins[i].name = symbols[i];
margins[i].calcMode = (ENUM_SYMBOL_CALC_MODE)flags[i][0];
margins[i].hedgeLeg = (bool)flags[i][1];
margins[i].initial = values[i][0];
margins[i].maintenance = values[i][1];
margins[i].hedged = values[i][2];
}
}
...
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Bây giờ chúng ta hiển thị thống kê trong nhật ký.
PrintFormat("===== Chế độ tính toán ký quỹ cho các ký hiệu %s =====",
(UseMarketWatch ? "Market Watch" : "tất cả có sẵn"),
(ExcludeZeroInitMargin || ExcludeZeroMainMargin || ExcludeZeroHedgeMargin
? "(có điều kiện) " : ""));
PrintFormat("Tổng số ký hiệu: %d", n);
PrintFormat("Phía hedging được sử dụng trong: %d", hedgeLeg);
PrintFormat("Số lần ký quỹ bằng không: ban đầu=%d, duy trì=%d, hedging=%d",
zeroInit, zeroMaintenance, zeroHedged);
Print("Thống kê theo chế độ tính toán:");
stats.print();
...
2
3
4
5
6
7
8
9
10
11
12
Vì các thành viên của liệt kê ENUM_SYMBOL_CALC_MODE
được hiển thị dưới dạng số nguyên (không quá rõ ràng), chúng ta cũng hiển thị một văn bản nơi mỗi giá trị có tên (từ EnumToString
).
Print("Chú thích: khóa=chế độ tính toán, giá trị=số lượng");
for(int i = 0; i < stats.getSize(); ++i)
{
PrintFormat("%d -> %s", stats.getKey(i), EnumToString(stats.getKey(i)));
}
...
2
3
4
5
6
Nếu cần thông tin chi tiết về các ký hiệu được chọn, chúng ta xuất mảng cấu trúc margins
.
if(ShowPerSymbolDetails)
{
Print("Cài đặt theo ký hiệu:");
ArrayPrint(margins);
}
}
2
3
4
5
6
Hãy chạy kịch bản vài lần với các cài đặt khác nhau. Bắt đầu với cài đặt mặc định.
===== Chế độ tính toán ký quỹ cho tất cả các ký hiệu có sẵn =====
Tổng số ký hiệu: 131
Phía hedging được sử dụng trong: 14
Số lần ký quỹ bằng không: ban đầu=123, duy trì=130, hedging=32
Thống kê theo chế độ tính toán:
[key] [value]
[0] 0 101
[1] 4 16
[2] 1 1
[3] 2 11
[4] 5 2
Chú thích: khóa=chế độ tính toán, giá trị=số lượng
0 -> SYMBOL_CALC_MODE_FOREX
4 -> SYMBOL_CALC_MODE_CFDLEVERAGE
1 -> SYMBOL_CALC_MODE_FUTURES
2 -> SYMBOL_CALC_MODE_CFD
5 -> SYMBOL_CALC_MODE_FOREX_NO_LEVERAGE
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Đối với lần chạy thứ hai, hãy đặt ShowPerSymbolDetails
và ExcludeZeroInitMargin
thành true
. Điều này yêu cầu thông tin chi tiết về tất cả các ký hiệu có giá trị ký quỹ ban đầu khác không.
===== Chế độ tính toán ký quỹ cho tất cả các ký hiệu có sẵn (có điều kiện) =====
Tổng số ký hiệu: 8
Phía hedging được sử dụng trong: 0
Số lần ký quỹ bằng không: ban đầu=0, duy trì=7, hedging=0
Thống kê theo chế độ tính toán:
[key] [value]
[0] 0 5
[1] 1 1
[2] 5 2
Chú thích: khóa=chế độ tính toán, giá trị=số lượng
0 -> SYMBOL_CALC_MODE_FOREX
1 -> SYMBOL_CALC_MODE_FUTURES
5 -> SYMBOL_CALC_MODE_FOREX_NO_LEVERAGE
Cài đặt theo ký hiệu:
[name] [calcMode] [hedgeLeg] [initial] [maintenance] [hedged]
[0] "XAUEUR" 0 false 100.00000 0.00000 50.00000
[1] "XAUAUD" 0 false 100.00000 0.00000 100.00000
[2] "XAGEUR" 0 false 1000.00000 0.00000 1000.00000
[3] "USDGEL" 0 false 100000.00000 100000.00000 50000.00000
[4] "SP500m" 1 false 6600.00000 0.00000 6600.00000
[5] "XBRUSD" 5 false 100.00000 0.00000 50.00000
[6] "XNGUSD" 0 false 10000.00000 0.00000 10000.00000
[7] "XTIUSD" 5 false 100.00000 0.000 Maverick
50.00000
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24