Author: Roberto Jacobs (3rjfx) | Featured on Forex Home Expert
- Introduction
- 1. Decoding the Input Properties: The Command Center
- 2. The Initialization Engine: void MCEA::Exp_MAxTenkanKijun_Config()
- 3. The Hybrid Signal Core: int MCEA::MAxIchiTK()
- 4. Execution Logic: GetOpenPosition and GetClosePosition
- 5. Advanced Profit Protection: bool MCEA::PartialCloseOrder()
- FAQ: Common Questions About Exp_MAxTenkanKijun
- Conclusion
Introduction
Welcome back to Forex Home Expert. In this fourth installment of our technical series, we are peeling back the layers of one of the most robust algorithmic trading tools available for MetaTrader 5: the Exp_MAxTenkanKijun.mq5.
This isn't just another simple crossover robot; it is a sophisticated Multi-Currency EA designed to navigate the complexities of the global forex market by combining two distinct technical philosophies: the trend-following power of Moving Averages and the equilibrium-based insights of the Ichimoku Kinko Hyo system.
For traders who have been following our journey, you know that finding an Expert Advisor MT5 capable of handling multiple pairs simultaneously without overloading the terminal is a rare find. The Exp_MAxTenkanKijun solves this by utilizing a unique class-based architecture (the MCEA class) that manages up to 30 currency pairs from a single chart.
Today, we will dissect the core engine of this robot, focusing specifically on its configuration, its hybrid signal generation logic known as MAxIchiTK, and a significantly improved Automated Partial Close mechanism that locks in profits while letting winners run.
Whether you are a seasoned algo-trader or new to the world of Algorithmic Trading, understanding the "why" and "how" behind these functions is crucial. We will explore how the MA Cross Tenkan-sen and MA Cross Kijun-sen interactions create high-probability entry signals, and how the new trailing stop logic adapts dynamically after a partial close.
Let's dig deeper into the code that powers this 30 pair device.
1. Decoding the Input Properties: The Command Center
The foundation of any reliable Forex Trading Robot lies in its input parameters. In the Exp_MAxTenkanKijun.mq5 source code, lines 17 through 207 represent the "Command Center."
This section is not merely a list of variables; it is a comprehensive control panel that allows the user to tailor the 30 Pairs EA to their specific risk profile and market view.
Unlike simpler EAs that offer only lot size and stop loss inputs, this EA provides granular control over time zones, session filters, and money management.
The first critical grouping is the "Global Strategy EA Parameter". Here, the user selects the timeframe (tfinuse) on which the EA calculates signals. While the EA can trade on any chart, the internal logic operates on the selected timeframe (default H1).
This separation allows the EA to monitor M15 charts for entries while managing positions based on H4 trends, providing flexibility in execution speed versus trend stability.
Next, we encounter the "Indicators Input Properties". This is where the hybrid nature of the EA shines. Users can adjust the periods for the Ichimoku components: tenkan (default 9), kijun (default 26), and senkou (default 52). Crucially, there is also a dedicated Moving Average setting (maper, default 3) with selectable smoothing methods (EMA, SMA, etc.).
This specific combination—a fast MA crossing the slower Tenkan-sen or Kijun-sen—is the heartbeat of the MA Cross Over Ichimoku strategy. By exposing these variables, the EA allows traders to optimize for different volatility regimes.
A lower maper makes the EA more sensitive to short-term spikes, while a higher value filters out noise, essential when trading a basket of 30 Pairs.
The "Select Pairs to Trade" section highlights the multi-currency capability. The enum PairsTrade offers presets like All30, Usds, Eurs, and even Metal. However, the most powerful feature here is TrdWi (Trader Wishes). This allows users to input a custom string of pairs (e.g., "EURUSD,GBPJPY,XAUUSD"), making the EA adaptable to personal watchlists.
The code validates these pairs against a master list to ensure no typos lead to execution errors, a safety feature often missing in commercial EAs.
Money Management is handled with professional rigor in the "Money Management Lot Size Parameter" group. The EA supports both FixedLot and DynamLot (Dynamic Lot). When Dynamic is selected, the Risk parameter (percentage of equity) drives the position sizing.
This is vital for a multi-currency EA because exposure across 30 pairs can compound quickly. Additionally, the inclusion of a Martingale option (UseMartin) with three distinct multipliers (lotmp1, lotmp2, lotmp3) offers a recovery mechanism for drawdowns, though it should be used with extreme caution.
The maxmrgn parameter acts as a circuit breaker, preventing new trades if free margin drops below a certain percentage of equity, protecting the account from margin calls during high-volatility events.
Time management is equally sophisticated. The "Trade on Specific Time" and "Day Trading On/Off" sections allow the EA to operate only during optimal liquidity windows. You can select predefined sessions like New_Zealand, Asia_Tokyo, Europe_London, or US_New_York, or define a Cus_Session (Custom Session).
This is critical for avoiding the "choppy" low-volume periods where the MA Cross Tenkan-sen signals might generate false positives. The ability to toggle specific days (e.g., turning off Sunday/Friday) further refines the strategy, acknowledging that market behavior changes drastically around the weekly open and close.
Finally, the "Trade & Order management Parameter" section integrates the advanced exit strategies.
Beyond standard Stop Loss (SLval) and Take Profit (TPval), we see controls for Automated Partial Close (PartialClose, profitinpips, percentlots) and two types of trailing mechanisms: Trailing Stop Loss and Trailing Take Profit.
The TrailingSL can be triggered by price, indicator, or High/Low bars, offering three distinct ways to protect profits. This level of detail in the input properties transforms the EA from a simple signal generator into a complete trade management system.
//+------------------------------------------------------------------+
//| Include |
//+------------------------------------------------------------------+
#include <Trade\Trade.mqh>
#include <Trade\PositionInfo.mqh>
#include <Trade\SymbolInfo.mqh>
#include <Trade\AccountInfo.mqh>
#include <Indicators\Indicator.mqh>
//--
CTrade mc_trade;
CSymbolInfo mc_symbol;
CPositionInfo mc_position;
CAccountInfo mc_account;
CIndicator mc_indicator;
//---
//--
enum tm_zone
{
Cus_Session, // Trading on Custom Session
New_Zealand, // Trading on New Zealand Session
Australia, // Trading on Autralia Sydney Session
Asia_Tokyo, // Trading on Asia Tokyo Session
Europe_London, // Trading on Europe London Session
US_New_York // Trading on US New York Session
};
//--
enum swhour
{
hr_00=0, // 00:00
hr_01=1, // 01:00
hr_02=2, // 02:00
hr_03=3, // 03:00
hr_04=4, // 04:00
hr_05=5, // 05:00
hr_06=6, // 06:00
hr_07=7, // 07:00
hr_08=8, // 08:00
hr_09=9, // 09:00
hr_10=10, // 10:00
hr_11=11, // 11:00
hr_12=12, // 12:00
hr_13=13, // 13:00
hr_14=14, // 14:00
hr_15=15, // 15:00
hr_16=16, // 16:00
hr_17=17, // 17:00
hr_18=18, // 18:00
hr_19=19, // 19:00
hr_20=20, // 20:00
hr_21=21, // 21:00
hr_22=22, // 22:00
hr_23=23 // 23:00
};
//--
enum inmnt
{
mn_00=0, // Minute 0
mn_05=5, // Minute 5
mn_10=10, // Minute 10
mn_15=15, // Minute 15
mn_20=20, // Minute 20
mn_25=25, // Minute 25
mn_30=30, // Minute 30
mn_35=35, // Minute 35
mn_40=40, // Minute 40
mn_45=45, // Minute 45
mn_50=50, // Minute 50
mn_55=55 // Minute 55
};
//--
enum PairsTrade
{
All30, // All Forex 30 Pairs
TrdWi, // Trader Wishes Pairs
Usds, // Forex USD Pairs
Eurs, // Forex EUR Pairs
Gbps, // Forex GBP Pairs
Auds, // Forex AUD Pairs
Nzds, // Forex NZD Pairs
Cads, // Forex CDD Pairs
Chfs, // Forex CHF Pairs
Jpys, // Forex JPY Pairs
Metal // Metal Pairs
};
//--
enum YN
{
No,
Yes
};
//--
enum mmt
{
FixedLot, // Fixed Lot Size
DynamLot // Dynamic Lot Size
};
//--
enum TFUSE
{
TFM15, // PERIOD_M15
TFM30, // PERIOD_M30
TFH1, // PERIOD_H1
TFH2, // PERIOD_H2
TFH3, // PERIOD_H3
TFH4, // PERIOD_H4
TFH6, // PERIOD_H6
TFH8, // PERIOD_H8
TFH12, // PERIOD_H12
TFD1 // PERIOD_D1
};
//--
enum TrType
{
byprice, // Trailing Stop by Price
byindi, // Trailing Stop by Indicator
byHiLo // Trailing Stop in HIGH or LOW bar
};
//--
enum MS
{
SP, // Single Pair
MP // Multi Pairs
};
//--
//---
input group "=== Global Strategy EA Parameter ==="; // Global Strategy EA Parameter
input TFUSE tfinuse = TFH1; // Select Expert TimeFrame, default PERIOD_H1
//---
input group "=== Indicators Input Properties ==="; // Indicators Input Properties
input int tenkan = 9; // Period of Tenkan-sen
input int kijun = 26; // Period of Kijun-sen
input int senkou = 52; // Period of Senkou Span B
input int maper = 3; // The Moving Average period
input ENUM_MA_METHOD method_ma = MODE_EMA; // MA Type of smoothing
input ENUM_APPLIED_PRICE priceMa = PRICE_CLOSE; // MA Applied Price
//---
input group "=== Select Pairs to Trade ==="; // Selected Pairs to trading
input MS trademode = MP; // Select Trading Pairs Mode (Multi or Single)
input PairsTrade usepairs = All30; // Select Pairs to Use
input string traderwishes = "eg. eurusd,usdchf"; // If Use Trader Wishes Pairs, input pair name here, separate by comma
//--
input group "=== Money Management Lot Size Parameter ==="; // Money Management Lot Size Parameter
input mmt mmlot = DynamLot; // Money Management Type
input double Risk = 5.0; // Percent Equity Risk per Trade (Min=1.0% / Max=10.0%)
input double Lots = 0.01; // Input Manual Lot Size FixedLot
input double maxmrgn = 80.0; // Input Maximum Free Margin from Equity to Trade (in Percent)
input YN UseMartin = Yes; // Select to use Martingale method (Yes) or (No)
input double lotmp1 = 2.00; // If use Martingale Input 2-nd Lot (lotmp1 x Lots) Multiplier
input double lotmp2 = 2.00; // If use Martingale Input 3-rd Lot (lotmp2 x 2nd) Multiplier
input double lotmp3 = 2.00; // If use Martingale Input 4-rd Lot (lotmp3 x 3rd) Multiplier
//--Trade on Specific Time
input group "=== Trade on Specific Time ==="; // Trade on Specific Time
input YN trd_time_zone = Yes; // Select If You Like to Trade on Specific Time Zone
input tm_zone session = Cus_Session; // Select Trading Time Zone
input swhour stsescuh = hr_00; // Time Hour to Start Trading Custom Session (0-23)
input inmnt stsescum = mn_15; // Time Minute to Start Trading Custom Session (0-55)
input swhour clsescuh = hr_23; // Time Hour to Stop Trading Custom Session (0-23)
input inmnt clsescum = mn_55; // Time Minute to Stop Trading Custom Session (0-55)
//--Day Trading On/Off
input group "=== Day Trading On/Off ==="; // Day Trading On/Off
input YN ttd0 = No; // Select Trading on Sunday (Yes) or (No)
input YN ttd1 = Yes; // Select Trading on Monday (Yes) or (No)
input YN ttd2 = Yes; // Select Trading on Tuesday (Yes) or (No)
input YN ttd3 = Yes; // Select Trading on Wednesday (Yes) or (No)
input YN ttd4 = Yes; // Select Trading on Thursday (Yes) or (No)
input YN ttd5 = Yes; // Select Trading on Friday (Yes) or (No)
input YN ttd6 = No; // Select Trading on Saturday (Yes) or (No)
//--Trade & Order management Parameter
input group "=== Trade & Order management Parameter ==="; // Trade & Order management Parameter
input YN use_sl = No; // Use Order Stop Loss (Yes) or (No)
input YN autosl = Yes; // Use Automatic Calculation Stop Loss (Yes) or (No)
input double SLval = 30.0; // If Not Use Automatic SL - Input SL value in Pips
input YN use_tp = Yes; // Use Order Take Profit (Yes) or (No)
input YN autotp = Yes; // Use Automatic Calculation Take Profit (Yes) or (No)
input double TPval = 60.0; // If Not Use Automatic TP - Input TP value in Pips
input YN PartialClose = Yes; // Use Partial Close Profit (Yes) or (No)
input double profitinpips = 15.0; // Input Profit in Pips for Partial Close, default 10 Pips
input double percentlots = 50.0; // Percentage Lot Size to Partial Close
input YN TrailingSL = Yes; // Use Trailing Stop Loss (Yes) or (No)
input TrType trlby = byindi; // Select Trailing Stop Type
input double TSval = 10.0; // If Use Trailing Stop by Price Input value in Pips
input double TSmin = 5.0; // Minimum Pips to start Trailing Stop
input YN TrailingTP = Yes; // Use Trailing Take Profit (Yes) or (No)
input double TPmin = 25.0; // Input Trailing Profit Value in Pips
input YN Close_by_Opps = Yes; // Close Trade By Opposite Signal (Yes) or (No)
input YN SaveOnRev = Yes; // Close Trade and Save profit due to weak signal (Yes) or (No)
input YN CheckVSLTP = No; // Check Virtual SL/TP & Close Loss Trade (Yes) or (No)
//--Others Expert Advisor Parameter
input group "=== Others Expert Advisor Parameter ==="; // Others EA Parameter
input YN alerts = Yes; // Display Alerts / Messages (Yes) or (No)
input YN UseEmailAlert = No; // Email Alert (Yes) or (No)
input YN UseSendnotify = No; // Send Notification (Yes) or (No)
input YN trade_info_display = Yes; // Select Display Trading Info on Chart (Yes) or (No)
input ulong magicEA = 20260608; // Expert ID (Magic Number)
//---
//---------//
***Copyright © 2026 3rjfx ~ For educational purposes only.***
2. The Initialization Engine: void MCEA::Exp_MAxTenkanKijun_Config()
Before a single tick is processed, the Expert Advisor MT5 must build its internal infrastructure. The function void MCEA::Exp_MAxTenkanKijun_Config() serves as this initialization engine.
Called within OnInit(), this method is responsible for translating the user's input properties into active system resources. It is the bridge between the static settings defined in lines 17-207 and the dynamic runtime environment.
The primary task of this configuration function is HandlingSymbolArrays. Since this is a 30 Pairs EA, the system cannot rely on the chart's symbol alone. The function iterates through the selected pair groups (e.g., All30, USD pairs) and populates the DIRI[] array with the actual symbol names.
Crucially, it also handles broker-specific prefixes and suffixes (e.g., "EURUSD.pro" or "EURUSDm"). The helper function SetSymbolNamePS() detects these variations automatically, ensuring that the EA attempts to trade the correct instrument regardless of the broker's naming convention.
Without this step, a multi-currency EA would fail instantly on non-standard accounts.
Another critical operation in Exp_MAxTenkanKijun_Config is the creation of Indicator Handles. For every symbol in the trading list, the EA must instantiate handles for:
- iMA: The fast Moving Average (e.g., EMA 3) used for the crossover trigger.
- iIchimoku: The full Ichimoku Kinko Hyo indicator to access Tenkan-sen, Kijun-sen, and Senkou Span B buffers.
- iMA (SMA 20): A secondary moving average used specifically for the "byindi" Trailing Stop logic.
Creating these handles inside a loop for up to 30 pairs is computationally intensive. The configuration function optimizes this by storing the handles in arrays (hichiMA[], hiChimk[], hSMA20[]) indexed by the symbol's position in the DIRI array.
This allows the OnTick function to retrieve indicator values instantly via CopyBuffer without re-initializing indicators on every tick, which is essential for maintaining performance in Algorithmic Trading.
The function also calculates the Maximum Allowed Orders (ALO). It checks the account's limit orders and adjusts the cap based on whether the "Close by Opposite Signal" feature is enabled.
If the EA is allowed to reverse positions, it needs room for both Buy and Sell orders; otherwise, it restricts the count to prevent over-exposure.
This dynamic calculation ensures that the Forex Trading Robot respects the broker's limits while maximizing the utility of the 30 Pairs strategy.
Furthermore, Exp_MAxTenkanKijun_Config sets up the Time Zone logic. It calculates the server time offset relative to GMT and pre-computes the start and end times for the selected trading session (New Zealand, Tokyo, London, NY, or Custom).
These timestamps are stored in variables like SesCuOp (Session Custom Open) and SesCuCl (Session Custom Close).
By doing this heavy lifting once at startup, the EA avoids complex time conversions during the heat of trading, ensuring that the MA Cross Kijun-sen signals are only acted upon during valid trading hours.
//+------------------------------------------------------------------+
//| Expert Configuration |
//+------------------------------------------------------------------+
void MCEA::Exp_MAxTenkanKijun_Config(void)
{
//---
//--
HandlingSymbolArrays(); // With this function we will handle all pairs that will be traded
//--
ENUM_TIMEFRAMES TFs[]={PERIOD_M15,PERIOD_M30,PERIOD_H1,PERIOD_H2,PERIOD_H3,PERIOD_H4,PERIOD_H6,PERIOD_H8,PERIOD_H12,PERIOD_D1};
int arTFs=ArraySize(TFs);
for(int x=0; x<arTFs; x++) if(tfinuse==x) { TFt=TFs[x]; break; } // TF for calculation signal
//-- Indicators handle for all symbol
for(int x=0; x<arrsymbx; x++)
{
hichiMA[x] = iMA(DIRI[x],TFt,maper,0,method_ma,priceMa); //-- Handle for the MA
hiChimk[x] = iIchimoku(DIRI[x],TFt,tenkan,kijun,senkou); //-- Handle for the Ichimoku indicator
hSMA20[x] = iMA(DIRI[x],TFt,20,0,MODE_SMA,PRICE_MEDIAN); //-- Handle for the SMA 20 indicator for Trailing Stop
//--
}
//--
TesterHideIndicators(true);
minprofit=NormalizeDouble(TSmin/100.0,2);
//--
ALO=(int)mc_account.LimitOrders()>sall ? sall : (int)mc_account.LimitOrders();
if(Close_by_Opps==No)
{
if((int)mc_account.LimitOrders()>=(sall*2)) ALO=sall*2;
else
ALO=(int)(mc_account.LimitOrders()/2);
}
//--
LotPS=(double)ALO;
Lotmpx[0]=lotmp1;
Lotmpx[1]=lotmp2;
Lotmpx[2]=lotmp3;
//--
mc_trade.SetExpertMagicNumber(magicEA);
mc_trade.SetDeviationInPoints(slip);
mc_trade.SetMarginMode();
Set_Time_Zone();
//--
return;
//---
} //-end Exp_MAxTenkanKijun Config()
//---------//
***Copyright © 2026 3rjfx ~ For educational purposes only.***
3. The Hybrid Signal Core: int MCEA::MAxIchiTK()
At the heart of the Exp_MAxTenkanKijun lies its proprietary signal generation function: int MCEA::MAxIchiTK(const string symbol). This function is what distinguishes this EA from generic Ichimoku or MA crossovers. It implements a dual-condition logic that requires confirmation from both the Moving Average and the Ichimoku Cloud components before generating a trade signal.
This filtration process is designed to reduce the false signals common in ranging markets, a frequent pitfall for multi-currency EA systems.
The function retrieves three key data streams for the specified symbol:
- MAIch[]: Values from the fast Moving Average (e.g., EMA 3).
- MITen[]: Values from the Ichimoku Tenkan-sen (Conversion Line).
- MIKij[]: Values from the Ichimoku Kijun-sen (Base Line).
The logic then evaluates four specific boolean conditions to determine direction. For a Bullish (Buy) signal, it looks for two scenarios:
- Rise1: The Tenkan-sen is above the Kijun-sen (
MITen[0] > MIKij[0]), AND the MA has recently crossed above the Tenkan-sen (MAIch[1] > MITen[1]), AND the MA is currently rising (MAIch[0] > MAIch[1]). This captures momentum when the price is already in an Ichimoku bullish structure. - Rise2: The Tenkan-sen is below or equal to the Kijun-sen, BUT the MA crosses above the Kijun-sen directly. This captures early reversals where the MA leads the Ichimoku lines.
Conversely, for a Bearish (Sell) signal, the logic mirrors these conditions: Tenkan below Kijun with MA crossing down Tenkan, or MA crossing down Kijun directly. By requiring the MA to interact with *either* the Tenkan or the Kijun while respecting their relative hierarchy, the MA Cross Over Ichimoku strategy creates a robust filter.
It avoids entering trades when the MA is whipsawing between the two lines without clear directional commitment.
This function returns an integer: 1 for Buy, -1 for Sell, and 0 for No Signal. This clean output is then consumed by the GetOpenPosition function.
The beauty of MAxIchiTK is its adaptability; by changing the maper input in the properties, traders can shift the sensitivity of this cross. A period of 3 makes it a scalping tool, while a period of 8 or 13 transforms it into a swing trading filter suitable for the H4 timeframe.
This versatility is why it remains a cornerstone of effective Algorithmic Trading strategies.
int MCEA::MAxIchiTK(const string symbol) // MA xx Tenkan-sen & Kijun-sen for Open Position
{
//---
int ret=0;
int rise=1,
down=-1;
int barcalc=arper;
//--
double MAIch[],
MITen[],
MIKij[];
//--
ArrayResize(MAIch,barcalc,barcalc);
ArrayResize(MITen,barcalc,barcalc);
ArrayResize(MIKij,barcalc,barcalc);
ArraySetAsSeries(MAIch,true);
ArraySetAsSeries(MITen,true);
ArraySetAsSeries(MIKij,true);
//--
int xs=PairsIdxArray(symbol);
mc_indicator.Refresh(TFt);
//--
CopyBuffer(hichiMA[xs],0,0,barcalc,MAIch); // EMA 3 buffers
CopyBuffer(hiChimk[xs],0,0,barcalc,MITen); // Tenkan-sen buffers
CopyBuffer(hiChimk[xs],1,0,barcalc,MIKij); // Kijun-sen buffers
//--
bool rise1=(MITen[0]>MIKij[0] && MAIch[2]<=MITen[2] && MAIch[1]>MITen[1] && MAIch[0]>MAIch[1]);
bool down1=(MITen[0]<MIKij[0] && MAIch[2]>=MITen[2] && MAIch[1]<MITen[1] && MAIch[0]<MAIch[1]);
//-
bool rise2=(MITen[0]<=MIKij[0] && MAIch[2]<=MIKij[2] && MAIch[1]>MIKij[1] && MAIch[0]>MAIch[1]);
bool down2=(MITen[0]>=MIKij[0] && MAIch[2]>=MIKij[2] && MAIch[1]<MIKij[1] && MAIch[0]<MAIch[1]);
//--
if(rise1 || rise2) ret=rise;
if(down1 || down2) ret=down;
//--
return(ret);
//---
} //-end MAxIchiTK()
//---------//
***Copyright © 2026 3rjfx ~ For educational purposes only.***
Explanation of Figure 2: Visual representation of the MAxIchiTK logic. Note how the fast MA (yellow) interacts with the Tenkan (red) and Kijun (blue) lines to generate confirmed signals only when momentum aligns with the Ichimoku structure.
4. Execution Logic: GetOpenPosition and GetClosePosition
Signals are useless without precise execution logic. The Expert Advisor MT5 uses two companion functions to manage the lifecycle of a trade: int MCEA::GetOpenPosition() and int MCEA::GetClosePosition().
These functions act as the gatekeepers, ensuring that trades are opened only when conditions are perfect and closed when the thesis is invalidated.
GetOpenPosition adds a second layer of filtration to the raw signal from MAxIchiTK. It calls DirectionMove(), which analyzes the current candle's body size relative to the average pip value. Even if MAxIchiTK says "Buy," GetOpenPosition will return 0 (No Trade) if the current candle is too small or indecisive.
This prevents the EA from entering on "doji" candles or low-volume spikes that often precede reversals. Only when both the indicator alignment (MAxIchiTK == rise) and the price action momentum (dirmove == rise) agree does the function return a valid Buy or Sell signal.
This confluence approach is vital for a 30 Pairs EA to maintain a high win rate across diverse market conditions.
GetClosePosition is equally nuanced. It doesn't just wait for a fixed Take Profit. It actively monitors for signal invalidation. If the EA is in a Buy position, it watches for a "Bearish Cross" condition where the MA crosses below the Tenkan-sen or Kijun-sen, combined with a downward DirectionMove.
This allows the EA to exit trades early if the trend weakens, preserving capital that would otherwise be lost waiting for a hard Stop Loss. This dynamic exit capability is a hallmark of advanced Forex Trading Robot design, distinguishing it from basic grid or martingale systems.
Additionally, there is a specialized function GetCloseInWeakSignal. This is used in conjunction with the "Save On Reverse" input parameter. If the EA is in profit but detects a weak opposing signal, it can close the trade to "save" the profit rather than risking a reversal.
This function essentially acts as a breakeven-or-better trigger, ensuring that green trades don't turn red due to late-stage trend exhaustion.
int MCEA::GetOpenPosition(const string symbol) // Signal Open Position
{
//---
int ret=0;
int rise=1,
down=-1;
//--
int dirmove=DirectionMove(symbol,TFt);
int MAxIchiTK=MAxIchiTK(symbol);
//--
if(MAxIchiTK==rise && dirmove==rise) ret=rise;
if(MAxIchiTK==down && dirmove==down) ret=down;
//--
return(ret);
//---
} //-end GetOpenPosition()
//---------//
int MCEA::GetClosePosition(const string symbol,int exis) // Signal Close Position
{
//---
int ret=0;
int rise=1,
down=-1;
int barcalc=arper;
//--
double MAIch[],
MITen[],
MIKij[];
//--
ArrayResize(MAIch,barcalc,barcalc);
ArrayResize(MITen,barcalc,barcalc);
ArrayResize(MIKij,barcalc,barcalc);
ArraySetAsSeries(MAIch,true);
ArraySetAsSeries(MITen,true);
ArraySetAsSeries(MIKij,true);
//--
int xs=PairsIdxArray(symbol);
mc_indicator.Refresh(TFt);
//--
CopyBuffer(hichiMA[xs],0,0,barcalc,MAIch); // EMA 3 buffers
CopyBuffer(hiChimk[xs],0,0,barcalc,MITen); // Tenkan-sen buffers
CopyBuffer(hiChimk[xs],1,0,barcalc,MIKij); // Kijun-sen buffers
//--
bool risec=(MITen[0]<MIKij[0] && MAIch[2]<=MITen[2] && MAIch[1]>MITen[1]);
bool downc=(MITen[0]>MIKij[0] && MAIch[2]>=MITen[2] && MAIch[1]<MITen[1]);
//--
int dirmove=DirectionMove(symbol,TFt);
//--
if((exis==down) && (risec && dirmove==rise)) ret=rise;
if((exis==rise) && (downc && dirmove==down)) ret=down;
//--
return(ret);
//---
} //-end GetClosePosition()
//---------//
int MCEA::GetCloseInWeakSignal(const string symbol,int exis) // Signal Indicator Position Close in profit
{
//---
int ret=0;
int rise=1,
down=-1;
//--
if(exis==down && GetClosePosition(symbol,down)==rise) ret=rise;
if(exis==rise && GetClosePosition(symbol,rise)==down) ret=down;
//--
return(ret);
//---
} //-end GetCloseInWeakSignal()
//---------//
***Copyright © 2026 3rjfx ~ For educational purposes only.***
5. Advanced Profit Protection: bool MCEA::PartialCloseOrder()
One of the most significant updates in this version of the Exp_MAxTenkanKijun is the enhanced bool MCEA::PartialCloseOrder() function. In modern Algorithmic Trading, taking partial profits is not just a luxury; it's a necessity for psychological stability and equity curve smoothing.
This function has been rewritten to handle multiple stages of partial closes and, crucially, to adapt the Trailing Stop Loss dynamically after each reduction.
The function operates by iterating through all open positions for a specific symbol. It checks if the current profit in pips exceeds the profitinpips threshold (default 15 pips). If it does, and if the pcbx (partial close counter for buys) or pcsx (for sells) indicates that a previous partial hasn't been completed, it executes a PositionClosePartial.
The Improvement: Adaptive Trailing Stop
Previously, partial closes were isolated events. Now, the logic includes a post-close modification step. After the first partial close (e.g., closing 50% of the lot), the function immediately modifies the Stop Loss of the *remaining* position. Specifically, if pcbx[x] == 2 (meaning the second partial close stage is active or completed), the SL is moved to pcbpos[x] - (profitinpips * pip). This effectively locks in the profit from the first partial close as a safety buffer for the runner.
This creates a "Risk-Free Runner" scenario. Once the first target is hit and partially closed, the remaining position is protected by a Stop Loss that guarantees a net profit even if the market reverses immediately.
This is particularly effective for a multi-currency EA where trends can vary wildly between pairs. For volatile pairs like GBPJPY, this secures gains quickly; for steady trenders like EURUSD, the runner can capture extended moves with zero risk.
The function also respects the percentlots input, allowing traders to customize how much volume is peeled off at each stage. Whether you prefer a conservative 25% trim or an aggressive 75% bank, the Automated Partial Close logic handles the math and execution seamlessly.
Combined with the Trailing Take Profit feature mentioned in the inputs, this creates a comprehensive exit ecosystem that maximizes expectancy.
bool MCEA::PartialCloseOrder(const string symbx)
{
//---
ResetLastError();
//--
double partClsB=0.0;
double partClsS=0.0;
bool partcls=false;
//--
int x=PairsIdxArray(symbx);
Pips(symbx);
//--
int total=PositionsTotal();
//--
for(int i=total-1; i>=0; i--)
{
string symbol=PositionGetSymbol(i);
if(symbol==symbx && mc_position.Magic()==magicEA)
{
ENUM_POSITION_TYPE opstype = mc_position.PositionType();
if(opstype==POSITION_TYPE_BUY)
{
RefreshTick(symbol);
double price = mc_position.PriceCurrent();
double pos_open = mc_position.PriceOpen();
double partClsB = pcbx[x]==0 ? mc_symbol.NormalizePrice(price-pos_open) : mc_symbol.NormalizePrice(price-pcbpos[x]);
double pos_vol = mc_position.Volume();
double part_vol = NormalizeDouble((pos_vol*(percentlots/100.0)),LotDig(symbx));
bool close_comp = (pos_vol-part_vol)<mc_symbol.LotsMin();
//--
double vol_close = pos_vol==mc_symbol.LotsMin() ? pos_vol : (pos_vol-part_vol)>mc_symbol.LotsMin() ?
part_vol : (pos_vol-part_vol)<mc_symbol.LotsMin() ? pos_vol : (pos_vol-mc_symbol.LotsMin());
vol_close=NormalizeDouble(vol_close,LotDig(symbx));
//--
bool closePartBuy = (partClsB>=(profitinpips*pip));
//--
if(closePartBuy) partcls=mc_trade.PositionClosePartial(symbx,vol_close,slip);
if(partcls)
{
pcbx[x]++;
pcbpos[x] = mc_symbol.NormalizePrice(price);
//--
string remvol=pos_vol-part_vol > 0.0 ? "\n ~ Remaining Vol: "+DoubleToString(pos_vol-part_vol,LotDig(symbx)) : "";
Do_Alerts(symbol, DoubleToString(percentlots,2)+ "% Volume Cut for "+symbx+" Success!"+remvol);
//--
Sleep(500);
RefreshTick(symbx);
bool modislb=false;
double modpossl=pcbx[x]==2 ? mc_symbol.NormalizePrice(pcbpos[x]-(profitinpips*pip)) : 0.0;
if(modpossl!=0.0) modislb=mc_trade.PositionModify(symbol,modpossl,mc_position.TakeProfit());
if(modislb)
Do_Alerts(symbol, "Modify SL at the previous volume cut position "+symbx+" "+DoubleToString(modpossl,dgts)+" Success!");
//--
if(close_comp)
{
pcbx[x]=0;
pcbpos[x]=0.0;
}
//--
break;
}
}
if(opstype==POSITION_TYPE_SELL)
{
RefreshTick(symbol);
double price = mc_position.PriceCurrent();
double pos_open = mc_position.PriceOpen();
double partClsS = pcsx[x]==0 ? mc_symbol.NormalizePrice(pos_open-price) : mc_symbol.NormalizePrice(pcspos[x]-price);
double pos_vol = mc_position.Volume();
double part_vol = NormalizeDouble((pos_vol*(percentlots/100.0)),LotDig(symbx));
bool close_comp = (pos_vol-part_vol)<mc_symbol.LotsMin();
//--
double vol_close = pos_vol==mc_symbol.LotsMin() ? pos_vol : (pos_vol-part_vol)>mc_symbol.LotsMin() ?
part_vol : (pos_vol-part_vol)<mc_symbol.LotsMin() ? pos_vol : (pos_vol-mc_symbol.LotsMin());
vol_close=NormalizeDouble(vol_close,LotDig(symbx));
//--
bool closePartSell = (partClsS>=(profitinpips*pip));
//--
if(closePartSell) partcls=mc_trade.PositionClosePartial(symbx,vol_close,slip);
if(partcls)
{
pcsx[x]++;
pcspos[x] = mc_symbol.NormalizePrice(price);
//--
string remvol=pos_vol-part_vol > 0.0 ? "\n ~ Remaining Vol: "+DoubleToString(pos_vol-part_vol,LotDig(symbx)) : "";
Do_Alerts(symbol, DoubleToString(percentlots,2)+ "% Volume Cut for "+symbx+" Success!"+remvol);
//--
Sleep(500);
RefreshTick(symbx);
bool modisls=false;
double modpossl=pcsx[x]==2 ? mc_symbol.NormalizePrice(pcspos[x]+(profitinpips*pip)) : 0.0;
if(modpossl!=0.0) modisls=mc_trade.PositionModify(symbol,modpossl,mc_position.TakeProfit());
if(modisls)
Do_Alerts(symbol, "Modify SL at the previous volume cut position "+symbx+" "+DoubleToString(modpossl,dgts)+" Success!");
//--
if(close_comp)
{
pcsx[x]=0;
pcspos[x]=0.0;
}
//--
break;
}
}
}
}
//--
return(partcls);
//---
} //-end PartialCloseOrder()
//---------//
***Copyright © 2026 3rjfx ~ For educational purposes only.***
6. Frequently Asked Questions (FAQ)
Q: Can I use this EA on a micro account?
A: Yes. The Exp_MAxTenkanKijun includes a FixedLot mode where you can set lots as low as 0.01. Additionally, the DynamLot mode calculates size based on equity, so it will automatically scale down to minimum lot sizes on smaller accounts, making it suitable for various account types.
Q: Does the "30 Pairs" setting slow down my MT5 terminal?
A: Not necessarily. The EA uses a class-based architecture (MCEA) that efficiently manages indicator handles. However, running 30 pairs on M1 timeframe will consume more resources than H1. It is recommended to use H1 or H4 for the MA Cross Over Ichimoku strategy to balance performance and signal quality.
Q: How does the Martingale feature work with Partial Close?
A: They operate independently but complementarily. Martingale increases lot size after a loss to recover drawdown. Partial Close reduces exposure on winning trades. Using them together requires careful calibration; ensure your maxmrgn is set conservatively (e.g., 50%) to prevent margin exhaustion if multiple martingale levels coincide with partial closes.
Q: Can I trade metals like Gold (XAUUSD) with this EA?
A: Absolutely. The PairsTrade enum includes a Metal option specifically for XAUUSD and XAGUSD. The MA Cross Tenkan-sen logic works exceptionally well on Gold due to its strong trending characteristics, though you may want to increase the SLval and TPval inputs to accommodate higher volatility.
Q: What happens if my broker changes symbol names (e.g., EURUSD to EURUSDm)?
A: The SetSymbolNamePS() function in the configuration phase automatically detects prefixes and suffixes. As long as the core 6-character ISO code (e.g., EURUSD) is present, the EA will map the correct symbol and execute trades without manual intervention.
Conclusion
The Exp_MAxTenkanKijun.mq5 represents a mature evolution in Expert Advisor MT5 development. By integrating the MA Cross Over Ichimoku strategy with robust multi-currency management, it offers traders a tool that is both versatile and precise. The detailed input properties allow for extensive customization, while the internal logic—specifically the MAxIchiTK signal generator and the enhanced PartialCloseOrder function—demonstrates a deep understanding of market mechanics.
For those seeking a Forex Trading Robot that goes beyond simple indicators, this EA provides a framework for sustainable algorithmic trading. The ability to trade 30 pairs with adaptive trailing stops and automated profit banking makes it a standout candidate for portfolio diversification. As always, we recommend testing the 30 Pairs EA on a demo account first to fine-tune the Trailing Stop Loss and Trailing Take Profit parameters to your specific broker's conditions. Happy trading, and may your algorithms be ever profitable!
⚠️ Important: Risk Disclaimer
- Demo Testing: You are strongly advised to test this EA on an MT5 Demo Account first to witness how it manages 30 pairs simultaneously.
- Real Account Trading: If you proceed to use this EA for automated trading on a Real Account, you do so at your own risk. Algorithmic trading involves substantial risk to your capital.
- Always remember the rules: Never trade with money you cannot afford to lose.
- Trading foreign exchange on margin carries a high level of risk and may not be suitable for all investors. The high degree of leverage can work against you as well as for you. Before deciding to invest in foreign exchange, you should carefully consider your investment objectives, level of experience, and risk appetite.
- The Exp_MAxTenkanKijun logic provided in this article are for educational purposes and do not guarantee profits. Past performance is not indicative of future results.
- For more details, please read our full Risk Disclaimer and Terms of Service.
Vital Records
We hope that this article and the Exp_MAxTenkanKijun - MQL5 Multi-Currency Expert Advisor program will be useful for traders in learning and generating new ideas, thereby will be able improving your trading performance.
See you in the next article on Expert Advisor programs or indicators for MetaTrader 4 and MetaTrader 5.
If you have any ideas for developing this EA program or have a new ideas, please leave your comments below this article.
Thanks for reading this article.
Explore more algorithmic trading resources:
- Content Sitemap – All articles and pages.
- Categories – Browse by topic (Indicators, EA, Python, etc).
Note: Please see the source program and download at the bottom of this article.
Risk Warning:
Trading Forex and CFDs involves significant risk and may not be suitable for all investors.
Trading in Forex and Contract for Difference (CFDs) entails a high risk of losing capital.
Before investing, always do your own research and never risk more than you can afford to lose.
All content provided is for educational purposes only and does not constitute financial advice.
//+------------------------------------------------------------------+
//| Exp_MAxTenkanKijun.mq5 |
//| Copyright 2026, Roberto Jacobs (3rjfx) ~ Date: 2026-06-08 |
//| https://www.mql5.com/en/users/3rjfx |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026, Roberto Jacobs (3rjfx) ~ Date: 2026-06-08"
#property link "https://www.mql5.com/en/users/3rjfx"
#property version "1.00"
#property strict
#property description "The Expert Exp_MAxTenkanKijun is the Automated Trading Multi Currency Forex Expert Advisor"
#property description "for MetaTrader 5 by using Moving Average and Ichimoku Indicator which trade Multiple Pairs in one Chart."
#property description "version: 1.00 ~ Update number: 1 ~ Last update: 2026/06/10 @14:34 (PM) WIT (Western Indonesian Time)"
//#property icon "\\Images\\Exp_MAxTenkanKijun.ico";
//+------------------------------------------------------------------+
//| Include |
//+------------------------------------------------------------------+
#include <Trade\Trade.mqh>
#include <Trade\PositionInfo.mqh>
#include <Trade\SymbolInfo.mqh>
#include <Trade\AccountInfo.mqh>
#include <Indicators\Indicator.mqh>
//--
CTrade mc_trade;
CSymbolInfo mc_symbol;
CPositionInfo mc_position;
CAccountInfo mc_account;
CIndicator mc_indicator;
//---
//--
enum tm_zone
{
Cus_Session, // Trading on Custom Session
New_Zealand, // Trading on New Zealand Session
Australia, // Trading on Autralia Sydney Session
Asia_Tokyo, // Trading on Asia Tokyo Session
Europe_London, // Trading on Europe London Session
US_New_York // Trading on US New York Session
};
//--
enum swhour
{
hr_00=0, // 00:00
hr_01=1, // 01:00
hr_02=2, // 02:00
hr_03=3, // 03:00
hr_04=4, // 04:00
hr_05=5, // 05:00
hr_06=6, // 06:00
hr_07=7, // 07:00
hr_08=8, // 08:00
hr_09=9, // 09:00
hr_10=10, // 10:00
hr_11=11, // 11:00
hr_12=12, // 12:00
hr_13=13, // 13:00
hr_14=14, // 14:00
hr_15=15, // 15:00
hr_16=16, // 16:00
hr_17=17, // 17:00
hr_18=18, // 18:00
hr_19=19, // 19:00
hr_20=20, // 20:00
hr_21=21, // 21:00
hr_22=22, // 22:00
hr_23=23 // 23:00
};
//--
enum inmnt
{
mn_00=0, // Minute 0
mn_05=5, // Minute 5
mn_10=10, // Minute 10
mn_15=15, // Minute 15
mn_20=20, // Minute 20
mn_25=25, // Minute 25
mn_30=30, // Minute 30
mn_35=35, // Minute 35
mn_40=40, // Minute 40
mn_45=45, // Minute 45
mn_50=50, // Minute 50
mn_55=55 // Minute 55
};
//--
enum PairsTrade
{
All30, // All Forex 30 Pairs
TrdWi, // Trader Wishes Pairs
Usds, // Forex USD Pairs
Eurs, // Forex EUR Pairs
Gbps, // Forex GBP Pairs
Auds, // Forex AUD Pairs
Nzds, // Forex NZD Pairs
Cads, // Forex CDD Pairs
Chfs, // Forex CHF Pairs
Jpys, // Forex JPY Pairs
Metal // Metal Pairs
};
//--
enum YN
{
No,
Yes
};
//--
enum mmt
{
FixedLot, // Fixed Lot Size
DynamLot // Dynamic Lot Size
};
//--
enum TFUSE
{
TFM15, // PERIOD_M15
TFM30, // PERIOD_M30
TFH1, // PERIOD_H1
TFH2, // PERIOD_H2
TFH3, // PERIOD_H3
TFH4, // PERIOD_H4
TFH6, // PERIOD_H6
TFH8, // PERIOD_H8
TFH12, // PERIOD_H12
TFD1 // PERIOD_D1
};
//--
enum TrType
{
byprice, // Trailing Stop by Price
byindi, // Trailing Stop by Indicator
byHiLo // Trailing Stop in HIGH or LOW bar
};
//--
enum MS
{
SP, // Single Pair
MP // Multi Pairs
};
//--
//---
input group "=== Global Strategy EA Parameter ==="; // Global Strategy EA Parameter
input TFUSE tfinuse = TFH1; // Select Expert TimeFrame, default PERIOD_H1
//---
input group "=== Indicators Input Properties ==="; // Indicators Input Properties
input int tenkan = 9; // Period of Tenkan-sen
input int kijun = 26; // Period of Kijun-sen
input int senkou = 52; // Period of Senkou Span B
input int maper = 3; // The Moving Average period
input ENUM_MA_METHOD method_ma = MODE_EMA; // MA Type of smoothing
input ENUM_APPLIED_PRICE priceMa = PRICE_CLOSE; // MA Applied Price
//---
input group "=== Select Pairs to Trade ==="; // Selected Pairs to trading
input MS trademode = MP; // Select Trading Pairs Mode (Multi or Single)
input PairsTrade usepairs = All30; // Select Pairs to Use
input string traderwishes = "eg. eurusd,usdchf"; // If Use Trader Wishes Pairs, input pair name here, separate by comma
//--
input group "=== Money Management Lot Size Parameter ==="; // Money Management Lot Size Parameter
input mmt mmlot = DynamLot; // Money Management Type
input double Risk = 5.0; // Percent Equity Risk per Trade (Min=1.0% / Max=10.0%)
input double Lots = 0.01; // Input Manual Lot Size FixedLot
input double maxmrgn = 80.0; // Input Maximum Free Margin from Equity to Trade (in Percent)
input YN UseMartin = Yes; // Select to use Martingale method (Yes) or (No)
input double lotmp1 = 2.00; // If use Martingale Input 2-nd Lot (lotmp1 x Lots) Multiplier
input double lotmp2 = 2.00; // If use Martingale Input 3-rd Lot (lotmp2 x 2nd) Multiplier
input double lotmp3 = 2.00; // If use Martingale Input 4-rd Lot (lotmp3 x 3rd) Multiplier
//--Trade on Specific Time
input group "=== Trade on Specific Time ==="; // Trade on Specific Time
input YN trd_time_zone = Yes; // Select If You Like to Trade on Specific Time Zone
input tm_zone session = Cus_Session; // Select Trading Time Zone
input swhour stsescuh = hr_00; // Time Hour to Start Trading Custom Session (0-23)
input inmnt stsescum = mn_15; // Time Minute to Start Trading Custom Session (0-55)
input swhour clsescuh = hr_23; // Time Hour to Stop Trading Custom Session (0-23)
input inmnt clsescum = mn_55; // Time Minute to Stop Trading Custom Session (0-55)
//--Day Trading On/Off
input group "=== Day Trading On/Off ==="; // Day Trading On/Off
input YN ttd0 = No; // Select Trading on Sunday (Yes) or (No)
input YN ttd1 = Yes; // Select Trading on Monday (Yes) or (No)
input YN ttd2 = Yes; // Select Trading on Tuesday (Yes) or (No)
input YN ttd3 = Yes; // Select Trading on Wednesday (Yes) or (No)
input YN ttd4 = Yes; // Select Trading on Thursday (Yes) or (No)
input YN ttd5 = Yes; // Select Trading on Friday (Yes) or (No)
input YN ttd6 = No; // Select Trading on Saturday (Yes) or (No)
//--Trade & Order management Parameter
input group "=== Trade & Order management Parameter ==="; // Trade & Order management Parameter
input YN use_sl = No; // Use Order Stop Loss (Yes) or (No)
input YN autosl = Yes; // Use Automatic Calculation Stop Loss (Yes) or (No)
input double SLval = 30.0; // If Not Use Automatic SL - Input SL value in Pips
input YN use_tp = Yes; // Use Order Take Profit (Yes) or (No)
input YN autotp = Yes; // Use Automatic Calculation Take Profit (Yes) or (No)
input double TPval = 60.0; // If Not Use Automatic TP - Input TP value in Pips
input YN PartialClose = Yes; // Use Partial Close Profit (Yes) or (No)
input double profitinpips = 15.0; // Input Profit in Pips for Partial Close, default 10 Pips
input double percentlots = 50.0; // Percentage Lot Size to Partial Close
input YN TrailingSL = Yes; // Use Trailing Stop Loss (Yes) or (No)
input TrType trlby = byindi; // Select Trailing Stop Type
input double TSval = 10.0; // If Use Trailing Stop by Price Input value in Pips
input double TSmin = 5.0; // Minimum Pips to start Trailing Stop
input YN TrailingTP = Yes; // Use Trailing Take Profit (Yes) or (No)
input double TPmin = 25.0; // Input Trailing Profit Value in Pips
input YN Close_by_Opps = Yes; // Close Trade By Opposite Signal (Yes) or (No)
input YN SaveOnRev = Yes; // Close Trade and Save profit due to weak signal (Yes) or (No)
input YN CheckVSLTP = No; // Check Virtual SL/TP & Close Loss Trade (Yes) or (No)
//--Others Expert Advisor Parameter
input group "=== Others Expert Advisor Parameter ==="; // Others EA Parameter
input YN alerts = Yes; // Display Alerts / Messages (Yes) or (No)
input YN UseEmailAlert = No; // Email Alert (Yes) or (No)
input YN UseSendnotify = No; // Send Notification (Yes) or (No)
input YN trade_info_display = Yes; // Select Display Trading Info on Chart (Yes) or (No)
input ulong magicEA = 20260608; // Expert ID (Magic Number)
//---
//---------//
//+------------------------------------------------------------------+
//| Class for working Expert Advisor |
//+------------------------------------------------------------------+
class MCEA
{
//---
private:
//----
int x_year; // Year
int x_mon; // Month
int x_day; // Day of the month
int x_hour; // Hour in a day
int x_min; // Minutes
int x_sec; // Seconds
//--
int oBm,
oSm,
ldig;
//--- Variables used in prefix and suffix symbols
int posCur1,
posCur2;
int inpre,
insuf;
bool symbfix;
string pre,suf;
string prefix,suffix;
//--- Variables are used in Trading Time Zone
int ishour,
onhour;
int pcbx[],
pcsx[];
datetime rem,
znop,
zncl,
zntm;
datetime SesCuOp,
SesCuCl,
Ses01Op,
Ses01Cl,
Ses02Op,
Ses02Cl,
Ses03Op,
Ses03Cl,
Ses04Op,
Ses04Cl,
Ses05Op,
Ses05Cl,
SesNoOp,
SesNoCl;
//--
string tz_ses,
tz_opn,
tz_cls;
//--
string tmopcu,
tmclcu,
tmop01,
tmcl01,
tmop02,
tmcl02,
tmop03,
tmcl03,
tmop04,
tmcl04,
tmop05,
tmcl05,
tmopno,
tmclno;
//----------------------
//--
double LotPS;
double point;
double slv,
tpv,
pip,
xpip;
double floatprofit,
fixclprofit;
double LastLotx[];
double Lotmpx[3];
double pcbpos[];
double pcspos[];
//--
string pairs,
hariini,
daytrade,
trade_mode;
//--
double OPEN[],
HIGH[],
LOW[],
CLOSE[];
datetime TIME[];
datetime closetime;
//--
//------------
//------------
void SetSymbolNamePS(void);
void HandlingSymbolArrays(void);
void Set_Time_Zone(void);
void Time_Zone(void);
//--
bool Trade_session(void);
bool CheckLastOrderIFLoss(const string symbx);
//--
int ThisTime(const int reqmode);
int ReqTime(datetime reqtime,const int reqmode);
int DirectionMove(const string symbol,const ENUM_TIMEFRAMES stf);
int MAxIchiTK(const string symbol);
int LotDig(const string symbol);
//--
double MLots(const string symbx);
double NonZeroDiv(double val1,double val2);
double OrderSLSet(const string xsymb,ENUM_ORDER_TYPE type,double atprice);
double OrderTPSet(const string xsymb,ENUM_ORDER_TYPE type,double atprice);
double SetOrderSL(const string xsymb,ENUM_POSITION_TYPE type,double atprice);
double SetOrderTP(const string xsymb,ENUM_POSITION_TYPE type,double atprice);
double TSPrice(const string xsymb,ENUM_POSITION_TYPE ptype,int TS_type);
double LotMartingale(const string symbol,double lotinit,double lastlot);
//--
string PosTimeZone(void);
string ReqDate(int d,int h,int m);
string TF2Str(ENUM_TIMEFRAMES period);
string timehr(int hr,int mn);
string TradingDay(void);
string AccountMode();
string GetCommentForOrder(void) { return(expname); }
//------------
public:
//---
//-- Exp_MAxTenkanKijun Config --
string DIRI[],
AS30[],
VSym[];
string SPC[];
string USD[];
string EUR[];
string GBP[];
string AUD[];
string NZD[];
string CAD[];
string CHF[];
string JPY[];
//--
string expname;
//--
//--- Indicators Handle
int hichiMA[];
int hiChimk[];
int hSMA20[];
//---
int ALO,
dgts,
arrsar,
arrsymbx;
int sall,
arusd,
areur,
aretc,
armet,
arspc,
arper;
ulong slip;
//--
double profitb[],
profits[];
double minprofit;
//--
int Buy,
Sell;
int ccur,
psec,
xtto,
TFArrays,
checktml;
int OpOr[],xob[],xos[];
//--
int year, // Year
mon, // Month
day, // Day
hour, // Hour
min, // Minutes
sec, // Seconds
dow, // Day of week (0-Sunday, 1-Monday, ... ,6-Saturday)
doy; // Day number of the year (January 1st is assigned the number value of zero)
//--
ENUM_TIMEFRAMES TFt;
ENUM_TIMEFRAMES TFASI[];
//--
datetime PbarB[],
TbarB[],
PbarS[],
TbarS[];
//--
bool PanelExtra;
//------------
MCEA(void);
~MCEA(void);
//------------
//--
virtual void Exp_MAxTenkanKijun_Config(void);
virtual void ExpertActionTrade(void);
//--
void ArraySymbolResize(void);
void CurrentSymbolSet(const string symbol);
void Pips(const string symbol);
void TradeInfo(void);
void Do_Alerts(const string symbx,string msgText);
void CheckOpenPMx(const string symbx);
void SetSLTPOrders(void);
void CloseAllOrders(void);
void CheckClose(const string symbx);
void TodayOrders(void);
void UpdatePrice(const string symbol,ENUM_TIMEFRAMES xtf,int bars);
void RefreshPrice(const string symbx,ENUM_TIMEFRAMES xtf,int bars);
//--
bool CheckEquityBalance(void);
bool RefreshTick(const string symbx);
bool TradingToday(void);
bool OpenBuy(const string symbol);
bool OpenSell(const string symbol);
bool ModifyOrderSLTP(double mStop,double ordtp);
bool ModifyOrdersSL(const string symbx,int TS_type);
bool ModifyOrdersTP(const string symbx);
bool PartialCloseOrder(const string symbol);
bool CloseAllProfit(void);
bool CloseAllLoss(void);
bool ManualCloseAllProfit(void);
bool CheckProfitLoss(const string symbol);
bool CloseBuyPositions(const string symbol);
bool CloseSellPositions(const string symbol);
bool CheckProfit(const string symbol,ENUM_POSITION_TYPE intype);
bool CheckLoss(const string symbol,ENUM_POSITION_TYPE intype,double slc=0.0);
bool IFNewBarsB(const string symbol);
bool IFNewBarsS(const string symbol);
bool GoodMarginTrade(const string symbol,ENUM_ORDER_TYPE _cmd,double lotsz,double atprice);
//--
int PairsIdxArray(const string symbol);
int TFIndexArray(ENUM_TIMEFRAMES TF);
int ValidatePairs(const string symbol);
int GetOpenPosition(const string symbol);
int GetClosePosition(const string symbol,int exis);
int GetCloseInWeakSignal(const string symbol,int exis);
//--
string getUninitReasonText(int reasonCode);
//--
//------------
//---
}; //-end class MCEA
//---------//
MCEA mc;
//---------//
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
MCEA::MCEA(void): x_year(0),
x_mon(0),
x_day(0),
x_hour(0),
x_min(0),
x_sec(0),
year(0),
mon(1),
day(2),
hour(3),
min(4),
sec(5),
dow(6),
doy(7),
psec(0),
Buy(1),
Sell(-1),
slip(16),
arper(125),
checktml(0),
expname("Exp_MAxTenkanKijun"),
closetime(TimeCurrent())
{
}
//---------//
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
MCEA::~MCEA(void)
{
}
//---------//
//+------------------------------------------------------------------+
//| Expert Configuration |
//+------------------------------------------------------------------+
void MCEA::Exp_MAxTenkanKijun_Config(void)
{
//---
//--
HandlingSymbolArrays(); // With this function we will handle all pairs that will be traded
//--
ENUM_TIMEFRAMES TFs[]={PERIOD_M15,PERIOD_M30,PERIOD_H1,PERIOD_H2,PERIOD_H3,PERIOD_H4,PERIOD_H6,PERIOD_H8,PERIOD_H12,PERIOD_D1};
int arTFs=ArraySize(TFs);
for(int x=0; x<arTFs; x++) if(tfinuse==x) { TFt=TFs[x]; break; } // TF for calculation signal
//-- Indicators handle for all symbol
for(int x=0; x<arrsymbx; x++)
{
hichiMA[x] = iMA(DIRI[x],TFt,maper,0,method_ma,priceMa); //-- Handle for the MA
hiChimk[x] = iIchimoku(DIRI[x],TFt,tenkan,kijun,senkou); //-- Handle for the Ichimoku indicator
hSMA20[x] = iMA(DIRI[x],TFt,20,0,MODE_SMA,PRICE_MEDIAN); //-- Handle for the SMA 20 indicator for Trailing Stop
//--
}
//--
TesterHideIndicators(true);
minprofit=NormalizeDouble(TSmin/100.0,2);
//--
ALO=(int)mc_account.LimitOrders()>sall ? sall : (int)mc_account.LimitOrders();
if(Close_by_Opps==No)
{
if((int)mc_account.LimitOrders()>=(sall*2)) ALO=sall*2;
else
ALO=(int)(mc_account.LimitOrders()/2);
}
//--
LotPS=(double)ALO;
Lotmpx[0]=lotmp1;
Lotmpx[1]=lotmp2;
Lotmpx[2]=lotmp3;
//--
mc_trade.SetExpertMagicNumber(magicEA);
mc_trade.SetDeviationInPoints(slip);
mc_trade.SetMarginMode();
Set_Time_Zone();
//--
return;
//---
} //-end Exp_MAxTenkanKijun Config()
//---------//
void MCEA::HandlingSymbolArrays(void)
{
//---
string All30[]={"EURUSD","GBPUSD","AUDUSD","NZDUSD","USDCAD","USDCHF","USDJPY","EURGBP",
"EURAUD","EURNZD","EURCAD","EURCHF","EURJPY","GBPAUD","GBPNZD","GBPCAD",
"GBPCHF","GBPJPY","AUDNZD","AUDCAD","AUDCHF","AUDJPY","NZDCAD","NZDCHF",
"NZDJPY","CADCHF","CADJPY","CHFJPY","XAUUSD","XAGUSD"}; // 30 pairs
string USDs[]={"USDCAD","USDCHF","USDJPY","AUDUSD","EURUSD","GBPUSD","NZDUSD","XAUUSD","XAGUSD"}; // USD pairs
string EURs[]={"EURAUD","EURCAD","EURCHF","EURGBP","EURJPY","EURNZD","EURUSD"}; // EUR pairs
string GBPs[]={"GBPAUD","GBPCAD","GBPCHF","EURGBP","GBPJPY","GBPNZD","GBPUSD"}; // GBP pairs
string AUDs[]={"AUDCAD","AUDCHF","EURAUD","GBPAUD","AUDJPY","AUDNZD","AUDUSD"}; // AUD pairs
string NZDs[]={"AUDNZD","NZDCAD","NZDCHF","EURNZD","GBPNZD","NZDJPY","NZDUSD"}; // NZD pairs
string CADs[]={"AUDCAD","CADCHF","EURCAD","GBPCAD","CADJPY","NZDCAD","USDCAD"}; // CAD pairs
string CHFs[]={"AUDCHF","CADCHF","EURCHF","GBPCHF","NZDCHF","CHFJPY","USDCHF"}; // CHF pairs
string JPYs[]={"AUDJPY","CADJPY","CHFJPY","EURJPY","GBPJPY","NZDJPY","USDJPY"}; // JPY pairs
string MTLs[]={"XAUUSD","XAGUSD"}; // METAL pairs
//--
sall=ArraySize(All30);
arusd=ArraySize(USDs);
areur=ArraySize(EURs);
aretc=ArraySize(JPYs);
armet=ArraySize(MTLs);
ArrayResize(VSym,sall,sall);
ArrayCopy(VSym,All30,0,0,WHOLE_ARRAY);
//--
if(usepairs==TrdWi && StringFind(traderwishes,"eg.",0)<0)
{
string to_split=traderwishes; // A string to split into substrings pairs name
string sep=","; // A separator as a character
ushort u_sep; // The code of the separator character
//--- Get the separator code
u_sep=StringGetCharacter(sep,0);
//--- Split the string to substrings
int p=StringSplit(to_split,u_sep,SPC);
if(p>0)
{
for(int i=0; i<p; i++) StringToUpper(SPC[i]);
//--
for(int i=0; i<p; i++)
{
if(ValidatePairs(SPC[i])<0) ArrayRemove(SPC,i,1);
}
}
arspc=ArraySize(SPC);
}
//--
SetSymbolNamePS(); // With this function we will detect whether the Symbol Name has a prefix and/or suffix
//--
if(inpre>0 || insuf>0)
{
if(usepairs==TrdWi && arspc>0)
{
for(int t=0; t<arspc; t++)
{
SPC[t]=pre+SPC[t]+suf;
}
}
//--
for(int t=0; t<sall; t++)
{
All30[t]=pre+All30[t]+suf;
}
for(int t=0; t<arusd; t++)
{
USDs[t]=pre+USDs[t]+suf;
}
for(int t=0; t<areur; t++)
{
EURs[t]=pre+EURs[t]+suf;
}
for(int t=0; t<aretc; t++)
{
GBPs[t]=pre+GBPs[t]+suf;
}
for(int t=0; t<aretc; t++)
{
AUDs[t]=pre+AUDs[t]+suf;
}
for(int t=0; t<aretc; t++)
{
NZDs[t]=pre+NZDs[t]+suf;
}
for(int t=0; t<aretc; t++)
{
CADs[t]=pre+CADs[t]+suf;
}
for(int t=0; t<aretc; t++)
{
CHFs[t]=pre+CHFs[t]+suf;
}
for(int t=0; t<aretc; t++)
{
JPYs[t]=pre+JPYs[t]+suf;
}
}
//--
ArrayCopy(VSym,All30,0,0,WHOLE_ARRAY);
ArrayResize(AS30,sall,sall);
ArrayCopy(AS30,All30,0,0,WHOLE_ARRAY);
for(int x=0; x<sall; x++) {SymbolSelect(AS30[x],true);}
if(ValidatePairs(Symbol())>=0) symbfix=true;
if(!symbfix)
{
Alert("Expert Advisors will not trade on pairs "+Symbol());
Alert("-- "+expname+" -- ",Symbol()," -- expert advisor will be Remove from the chart.");
ExpertRemove();
}
//--
switch(usepairs)
{
case 0: // All Forex & Metal 30 Pairs
{
ArrayResize(DIRI,sall,sall);
arrsymbx=sall;
ArraySymbolResize();
ArrayCopy(DIRI,All30,0,0,WHOLE_ARRAY);
pairs="Multi Currency "+string(sall)+" Pairs";
//--
break;
}
case 1: // Trader wishes pairs
{
ArrayResize(DIRI,arspc,arspc);
arrsymbx=arspc;
ArraySymbolResize();
ArrayCopy(DIRI,SPC,0,0,WHOLE_ARRAY);
pairs="("+string(arspc)+") Trader Wishes Pairs";
//--
break;
}
case 2: // USD pairs
{
ArrayResize(DIRI,arusd,arusd);
arrsymbx=arusd;
ArraySymbolResize();
ArrayCopy(DIRI,USDs,0,0,WHOLE_ARRAY);
pairs="("+string(arusd)+") Multi Currency USD Pairs";
//--
break;
}
case 3: // EUR pairs
{
ArrayResize(DIRI,areur,areur);
arrsymbx=aretc;
ArraySymbolResize();
ArrayCopy(DIRI,EURs,0,0,WHOLE_ARRAY);
pairs="("+string(aretc)+") Forex EUR Pairs";
//--
break;
}
case 4: // GBP pairs
{
ArrayResize(DIRI,aretc,aretc);
arrsymbx=aretc;
ArraySymbolResize();
ArrayCopy(DIRI,GBPs,0,0,WHOLE_ARRAY);
pairs="("+string(aretc)+") Forex GBP Pairs";
//--
break;
}
case 5: // AUD pairs
{
ArrayResize(DIRI,aretc,aretc);
arrsymbx=aretc;
ArraySymbolResize();
ArrayCopy(DIRI,AUDs,0,0,WHOLE_ARRAY);
pairs="("+string(aretc)+") Forex AUD Pairs";
//--
break;
}
case 6: // NZD pairs
{
ArrayResize(DIRI,aretc,aretc);
arrsymbx=aretc;
ArraySymbolResize();
ArrayCopy(DIRI,NZDs,0,0,WHOLE_ARRAY);
pairs="("+string(aretc)+") Forex NZD Pairs";
//--
break;
}
case 7: // CAD pairs
{
ArrayResize(DIRI,aretc,aretc);
arrsymbx=aretc;
ArraySymbolResize();
ArrayCopy(DIRI,CADs,0,0,WHOLE_ARRAY);
pairs="("+string(aretc)+") Forex CAD Pairs";
//--
break;
}
case 8: // CHF pairs
{
ArrayResize(DIRI,aretc,aretc);
arrsymbx=aretc;
ArraySymbolResize();
ArrayCopy(DIRI,CHFs,0,0,WHOLE_ARRAY);
pairs="("+string(aretc)+") Forex CHF Pairs";
//--
break;
}
case 9: // JPY pairs
{
ArrayResize(DIRI,aretc,aretc);
arrsymbx=aretc;
ArraySymbolResize();
ArrayCopy(DIRI,JPYs,0,0,WHOLE_ARRAY);
pairs="("+string(aretc)+") Forex JPY Pairs";
//--
break;
}
case 10: // Metal pairs
{
ArrayResize(DIRI,armet,armet);
arrsymbx=armet;
ArraySymbolResize();
ArrayCopy(DIRI,MTLs,0,0,WHOLE_ARRAY);
pairs="("+string(armet)+") Metal Pairs";
//--
break;
}
}
//--
return;
//---
} //-end HandlingSymbolArrays()
//---------//
void MCEA::SetSymbolNamePS(void)
{
//---
int sym_Lenpre=0;
int sym_Lensuf=0;
string sym_pre="";
string sym_suf="";
SymbolSelect(Symbol(),true);
string insymbol=Symbol();
int inlen=StringLen(insymbol);
int toseek=-1;
string dep="";
string bel="";
string sym_use ="";
int pairx=-1;
string xcur[]={"EUR","GBP","AUD","NZD","USD","CAD","CHF"}; // 7 major currency
int xcar=ArraySize(xcur);
//--
for(int x=0; x<xcar; x++)
{
toseek=StringFind(insymbol,xcur[x],0);
if(toseek>=0)
{
pairx=x;
break;
}
}
if(pairx>=0)
{
int awl=toseek-3 <0 ? 0 : toseek-3;
int sd=StringFind(insymbol,"SD",0);
if(toseek==0 && sd<4)
{
dep=StringSubstr(insymbol,toseek,3);
bel=StringSubstr(insymbol,toseek+3,3);
sym_use=dep+bel;
}
else
if(toseek>0)
{
dep=StringSubstr(insymbol,toseek,3);
bel=StringSubstr(insymbol,toseek+3,3);
sym_use=dep+bel;
}
else
{
dep=StringSubstr(insymbol,awl,3);
bel=StringSubstr(insymbol,awl+3,3);
sym_use=dep+bel;
}
}
//--
string sym_nmx=sym_use;
int lensx=StringLen(sym_nmx);
//--
if(inlen>lensx && lensx==6)
{
sym_Lenpre=StringFind(insymbol,sym_nmx,0);
sym_Lensuf=inlen-lensx-sym_Lenpre;
//--
if(sym_Lenpre>0)
{
sym_pre=StringSubstr(insymbol,0,sym_Lenpre);
for(int i=0; i<xcar; i++)
if(StringFind(sym_pre,xcur[i],0)>=0) sym_pre="";
}
if(sym_Lensuf>0)
{
sym_suf=StringSubstr(insymbol,sym_Lenpre+lensx,sym_Lensuf);
for(int i=0; i<xcar; i++)
if(StringFind(sym_suf,xcur[i],0)>=0) sym_suf="";
}
}
//--
pre=sym_pre;
suf=sym_suf;
inpre=StringLen(pre);
insuf=StringLen(suf);
posCur1=inpre;
posCur2=posCur1+3;
//--
return;
//---
} //-end SetSymbolNamePS()
//---------//
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit(void)
{
//---
mc.Exp_MAxTenkanKijun_Config();
//--
return(INIT_SUCCEEDED);
//---
} //-end OnInit()
//---------//
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//---
Comment("");
//-- Release all handle indicators for all symbols
for(int x=0; x<mc.arrsymbx; x++)
{
IndicatorRelease(mc.hichiMA[x]);
IndicatorRelease(mc.hiChimk[x]);
IndicatorRelease(mc.hSMA20[x]);
}
//--
PrintFormat("%s: Deinitialization reason code=%d",__FUNCTION__,reason);
Print(mc.getUninitReasonText(reason));
ObjectsDeleteAll(0,0,OBJ_BUTTON);
ObjectsDeleteAll(0,0,OBJ_LABEL);
ObjectsDeleteAll(0,0,OBJ_RECTANGLE_LABEL);
//--
return;
//---
} //-end OnDeinit()
//---------//
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick(void)
{
//---
mc.ExpertActionTrade();
//--
return;
//---
} //-end OnTick()
//---------//
//+------------------------------------------------------------------+
void MCEA::ExpertActionTrade(void)
{
//---
//--Check Trading Terminal
ResetLastError();
//--
if(!MQLInfoInteger(MQL_TRADE_ALLOWED) && mc.checktml==0) //-- Check whether MT5 Algorithmic trading is Allow or Prohibit
{
mc.Do_Alerts(Symbol(),"Trading Expert at "+Symbol()+" are NOT Allowed by Setting.");
mc.checktml=1; //-- Variable checktml is given a value of 1, so that the alert is only done once.
return;
}
//--
if(!DisplayManualButton("M","C","R")) DisplayManualButton(); //-- Show the expert manual button panel
//--
if(trade_info_display==Yes) mc.TradeInfo(); //-- Displayed Trading Info on Chart
//---
//--
int mcsec=mc.ThisTime(mc.sec);
//--
if(fmod((double)mcsec,5.0)==0) mc.ccur=mcsec;
//--
if(mc.ccur!=mc.psec)
{
string symbol;
//-- Here we start with the rotation of the name of all symbol or pairs to be traded
for(int x=0; x<mc.arrsymbx && !IsStopped(); x++)
{
//--
switch(trademode)
{
case SP:
{
if(mc.DIRI[x]!=Symbol()) continue;
symbol=Symbol();
mc.pairs="Single Pair"+" ("+symbol+")";
break;
}
case MP:
{
if(mc.DIRI[x]==Symbol()) symbol=Symbol();
else symbol=mc.DIRI[x];
break;
}
}
//--
mc.CurrentSymbolSet(symbol);
//--
if(mc.TradingToday() && mc.Trade_session())
{
//--
mc.OpOr[x]=mc.GetOpenPosition(symbol); //-- Get trading signals to open positions
//-- //-- and store in the variable OpOr[x]
if(mc.OpOr[x]==mc.Buy) //-- If variable OpOr[x] get result of GetOpenPosition(symbol) as "Buy" (value=1)
{
//--
mc.CheckOpenPMx(symbol);
//--
if(Close_by_Opps==Yes && mc.xos[x]>0) { mc.CloseSellPositions(symbol); mc.OpenBuy(symbol); }
//--
if(mc.xob[x]==0 && mc.xtto<mc.ALO && mc.IFNewBarsB(symbol)) mc.OpenBuy(symbol);
else
if(mc.xtto>=mc.ALO)
{
//--
mc.Do_Alerts(symbol,"Maximum amount of open positions and active pending orders has reached"+
"\n the limit = "+string(mc.ALO)+" Orders ");
//--
mc.CheckOpenPMx(symbol);
//--
if(mc.xos[x]>0 && mc.profits[x]<-1.02 && mc.xob[x]==0) { mc.CloseSellPositions(symbol); mc.OpenBuy(symbol); }
else
mc.CloseAllProfit();
//--
}
}
if(mc.OpOr[x]==mc.Sell) //-- If variable OpOr[x] get result of GetOpenPosition(symbol) as "Sell" (value=-1)
{
//--
mc.CheckOpenPMx(symbol);
//--
if(Close_by_Opps==Yes && mc.xob[x]>0) { mc.CloseBuyPositions(symbol); mc.OpenSell(symbol); }
//--
if(mc.xos[x]==0 && mc.xtto<mc.ALO && mc.IFNewBarsS(symbol)) mc.OpenSell(symbol);
else
if(mc.xtto>=mc.ALO)
{
//--
mc.Do_Alerts(symbol,"Maximum amount of open positions and active pending orders has reached"+
"\n the limit = "+string(mc.ALO)+" Orders ");
//--
mc.CheckOpenPMx(symbol);
//--
if(mc.xob[x]>0 && mc.profitb[x]<-1.02 && mc.xos[x]==0) { mc.CloseBuyPositions(symbol); mc.OpenSell(symbol); }
else
mc.CloseAllProfit();
//--
}
}
}
//--
mc.CheckOpenPMx(symbol);
//--
if(mc.xtto>0)
{
//--
if(PartialClose==Yes) //-- Partial Close Order (Yes)
{
PartialCloseOrder(symbol);
}
//--
if(SaveOnRev==Yes) //-- Close Trade and Save profit due to weak signal (Yes)
{
mc.CheckOpenPMx(symbol);
if(mc.profitb[x]>mc.minprofit && mc.xob[x]>0 && mc.GetCloseInWeakSignal(symbol,mc.Buy)==mc.Sell)
{
mc.CloseBuyPositions(symbol);
mc.Do_Alerts(symbol,"Close BUY order "+symbol+" to save profit due to weak signal.");
}
if(mc.profits[x]>mc.minprofit && mc.xos[x]>0 && mc.GetCloseInWeakSignal(symbol,mc.Sell)==mc.Buy)
{
mc.CloseSellPositions(symbol);
mc.Do_Alerts(symbol,"Close SELL order "+symbol+" to save profit due to weak signal.");
}
}
//--
if(TrailingSL==Yes) mc.ModifyOrdersSL(symbol,trlby); //-- Use Trailing Stop Loss (Yes)
if(TrailingTP==Yes) mc.ModifyOrdersTP(symbol); //-- Use Trailing Take Profit (Yes)
}
//--
mc.CheckOpenPMx(symbol);
if(Close_by_Opps==No && (mc.xob[x]+mc.xos[x]>1))
{
mc.CheckProfitLoss(symbol);
mc.Do_Alerts(symbol,"Close order due stop in loss.");
}
//--
if(use_sl==No && CheckVSLTP==Yes)
{
if(!mc.CheckEquityBalance())
if(mc.CloseAllLoss())
mc.Do_Alerts(symbol,"Close order due stop in loss to secure equity.");
}
//--
mc.CheckClose(symbol);
}
//--
mc.psec=mc.ccur;
}
//--
return;
//---
} //-end ExpertActionTrade()
//---------//
int MCEA::PairsIdxArray(const string symbol)
{
//---
int pidx=-1;
//--
for(int x=0; x<arrsymbx; x++)
{
if(DIRI[x]==symbol)
{
pidx=x;
break;
}
}
//--
return(pidx);
//---
} //-end PairsIdxArray()
//---------//
int MCEA::TFIndexArray(ENUM_TIMEFRAMES TF)
{
//---
int res=-1;
//--
for(int x=0; x<TFArrays; x++)
{
if(TF==TFASI[x])
{
res=x;
break;
}
}
//--
return(res);
//---
} //-end TFIndexArray()
//---------//
int MCEA::ValidatePairs(const string symbol)
{
//---
int pidx=-1;
//--
for(int x=0; x<sall; x++)
{
if(VSym[x]==symbol)
{
pidx=x;
break;
}
}
//--
return(pidx);
//---
} //-end ValidatePairs()
//---------//
void MCEA::ArraySymbolResize(void)
{
//---
ArrayFree(DIRI);
ArrayFree(xob);
ArrayFree(xos);
ArrayFree(OpOr);
ArrayFree(pcbx);
ArrayFree(pcsx);
ArrayFree(profitb);
ArrayFree(profits);
ArrayFree(hichiMA);
ArrayFree(hiChimk);
ArrayFree(hSMA20);
ArrayFree(PbarB);
ArrayFree(TbarB);
ArrayFree(PbarS);
ArrayFree(TbarS);
ArrayFree(LastLotx);
ArrayFree(pcbpos);
ArrayFree(pcspos);
//--
ArrayResize(DIRI,arrsymbx,arrsymbx);
ArrayResize(xob,arrsymbx,arrsymbx);
ArrayResize(xos,arrsymbx,arrsymbx);
ArrayResize(OpOr,arrsymbx,arrsymbx);
ArrayResize(pcbx,arrsymbx,arrsymbx);
ArrayResize(pcsx,arrsymbx,arrsymbx);
ArrayResize(profitb,arrsymbx,arrsymbx);
ArrayResize(profits,arrsymbx,arrsymbx);
ArrayResize(hichiMA,arrsymbx,arrsymbx);
ArrayResize(hiChimk,arrsymbx,arrsymbx);
ArrayResize(hSMA20,arrsymbx,arrsymbx);
ArrayResize(PbarB,arrsymbx,arrsymbx);
ArrayResize(TbarB,arrsymbx,arrsymbx);
ArrayResize(PbarS,arrsymbx,arrsymbx);
ArrayResize(TbarS,arrsymbx,arrsymbx);
ArrayResize(LastLotx,arrsymbx,arrsymbx);
ArrayResize(pcbpos,arrsymbx,arrsymbx);
ArrayResize(pcspos,arrsymbx,arrsymbx);
//--
return;
//---
} //-end ArraySymbolResize()
//---------//
void MCEA::UpdatePrice(const string symbol,ENUM_TIMEFRAMES xtf,int bars=0)
{
//---
int xbar=bars==0 ? arper : bars;
//--
ArrayFree(OPEN);
ArrayFree(HIGH);
ArrayFree(LOW);
ArrayFree(CLOSE);
ArrayFree(TIME);
//--
ArrayResize(OPEN,xbar,xbar);
ArrayResize(HIGH,xbar,xbar);
ArrayResize(LOW,xbar,xbar);
ArrayResize(CLOSE,xbar,xbar);
ArrayResize(TIME,xbar,xbar);
//--
ArraySetAsSeries(OPEN,true);
ArraySetAsSeries(HIGH,true);
ArraySetAsSeries(LOW,true);
ArraySetAsSeries(CLOSE,true);
ArraySetAsSeries(TIME,true);
//--
ArrayInitialize(OPEN,0.0);
ArrayInitialize(HIGH,0.0);
ArrayInitialize(LOW,0.0);
ArrayInitialize(CLOSE,0.0);
ArrayInitialize(TIME,0);
//--
RefreshPrice(symbol,xtf,bars);
//--
int co=CopyOpen(symbol,xtf,0,xbar,OPEN);
int ch=CopyHigh(symbol,xtf,0,xbar,HIGH);
int cl=CopyLow(symbol,xtf,0,xbar,LOW);
int cc=CopyClose(symbol,xtf,0,xbar,CLOSE);
int ct=CopyTime(symbol,xtf,0,xbar,TIME);
//--
return;
//---
} //-end UpdatePrice()
//---------//
void MCEA::RefreshPrice(const string symbx,ENUM_TIMEFRAMES xtf,int bars)
{
//---
MqlRates parray[];
ArraySetAsSeries(parray,true);
int copied=CopyRates(symbx,xtf,0,bars,parray);
//--
return;
//---
} //-end RefreshPrice()
//---------//
bool MCEA::RefreshTick(const string symbx)
{
//---
mc_symbol.Name(symbx);
if(mc_symbol.RefreshRates()) return(true);
//--
return(false);
//---
} //-end RefreshTick()
//---------//
void MCEA::CurrentSymbolSet(const string symbol)
{
//---
mc_symbol.Name(symbol);
mc_symbol.CheckMarketWatch();
mc_symbol.IsSynchronized();
mc_trade.SetTypeFillingBySymbol(symbol);
mc_symbol.Refresh();
mc_symbol.RefreshRates();
//--
return;
//---
} //-end CurrentSymbolSet()
//---------//
void MCEA::Pips(const string symbol)
{
//---
CurrentSymbolSet(symbol);
//--
point=mc_symbol.Point();
dgts=(int)mc_symbol.Digits();
//--
xpip=10.0;
pip=point*xpip;
//--
return;
//---
} //-end Pips()
//---------//
bool MCEA::IFNewBarsB(const string symbol) // New bar check buy order
{
//---
bool Nb=false;
int xs=PairsIdxArray(symbol);
//--
TbarB[xs]=iTime(symbol,TFt,0);
if(TbarB[xs]!=PbarB[xs]) Nb=true;
//--
return(Nb);
//---
} //-end IFNewBarsB()
//---------//
bool MCEA::IFNewBarsS(const string symbol) // New bar check sell order
{
//---
bool Nb=false;
int xs=PairsIdxArray(symbol);
//--
TbarS[xs]=iTime(symbol,TFt,0);
if(TbarS[xs]!=PbarS[xs]) Nb=true;
//--
return(Nb);
//---
} //-end IFNewBarsS()
//---------//
bool MCEA::GoodMarginTrade(const string symbol,ENUM_ORDER_TYPE _cmd,double lotsz,double atprice)
{
//---
bool goodmrgn=true;
//--
if((mc_account.FreeMarginCheck(symbol,_cmd,lotsz,atprice)<=0.0)||(mc_account.FreeMargin()<(mc_account.Equity()*maxmrgn/100))) goodmrgn=false;
//--
if(!goodmrgn)
{
string nomargn="Account Free Margin minimum has reached the specified limit, Order will not opened";
Do_Alerts(symbol,nomargn);
}
//--
return(goodmrgn);
//---
} //-end GoodMarginTrade()
//---------//
int MCEA::DirectionMove(const string symbol,const ENUM_TIMEFRAMES stf) // Bar Price Direction
{
//---
int ret=0;
int rise=1,
down=-1;
//--
Pips(symbol);
double difud=mc_symbol.NormalizePrice(2.6*pip);
UpdatePrice(symbol,stf,2);
//--
if(CLOSE[0]>OPEN[0]+difud) ret=rise;
if(CLOSE[0]<OPEN[0]-difud) ret=down;
//--
return(ret);
//---
} //-end DirectionMove()
//---------//
int MCEA::MAxIchiTK(const string symbol) // MA xx Tenkan-sen & Kijun-sen for Open Position
{
//---
int ret=0;
int rise=1,
down=-1;
int barcalc=arper;
//--
double MAIch[],
MITen[],
MIKij[];
//--
ArrayResize(MAIch,barcalc,barcalc);
ArrayResize(MITen,barcalc,barcalc);
ArrayResize(MIKij,barcalc,barcalc);
ArraySetAsSeries(MAIch,true);
ArraySetAsSeries(MITen,true);
ArraySetAsSeries(MIKij,true);
//--
int xs=PairsIdxArray(symbol);
mc_indicator.Refresh(TFt);
//--
CopyBuffer(hichiMA[xs],0,0,barcalc,MAIch); // EMA 3 buffers
CopyBuffer(hiChimk[xs],0,0,barcalc,MITen); // Tenkan-sen buffers
CopyBuffer(hiChimk[xs],1,0,barcalc,MIKij); // Kijun-sen buffers
//--
bool rise1=(MITen[0]>MIKij[0] && MAIch[2]<=MITen[2] && MAIch[1]>MITen[1] && MAIch[0]>MAIch[1]);
bool down1=(MITen[0]<MIKij[0] && MAIch[2]>=MITen[2] && MAIch[1]<MITen[1] && MAIch[0]<MAIch[1]);
//-
bool rise2=(MITen[0]<=MIKij[0] && MAIch[2]<=MIKij[2] && MAIch[1]>MIKij[1] && MAIch[0]>MAIch[1]);
bool down2=(MITen[0]>=MIKij[0] && MAIch[2]>=MIKij[2] && MAIch[1]<MIKij[1] && MAIch[0]<MAIch[1]);
//--
if(rise1 || rise2) ret=rise;
if(down1 || down2) ret=down;
//--
return(ret);
//---
} //-end MAxIchiTK()
//---------//
int MCEA::GetOpenPosition(const string symbol) // Signal Open Position
{
//---
int ret=0;
int rise=1,
down=-1;
//--
int dirmove=DirectionMove(symbol,TFt);
int MAxIchiTK=MAxIchiTK(symbol);
//--
if(MAxIchiTK==rise && dirmove==rise) ret=rise;
if(MAxIchiTK==down && dirmove==down) ret=down;
//--
return(ret);
//---
} //-end GetOpenPosition()
//---------//
int MCEA::GetClosePosition(const string symbol,int exis) // Signal Close Position
{
//---
int ret=0;
int rise=1,
down=-1;
int barcalc=arper;
//--
double MAIch[],
MITen[],
MIKij[];
//--
ArrayResize(MAIch,barcalc,barcalc);
ArrayResize(MITen,barcalc,barcalc);
ArrayResize(MIKij,barcalc,barcalc);
ArraySetAsSeries(MAIch,true);
ArraySetAsSeries(MITen,true);
ArraySetAsSeries(MIKij,true);
//--
int xs=PairsIdxArray(symbol);
mc_indicator.Refresh(TFt);
//--
CopyBuffer(hichiMA[xs],0,0,barcalc,MAIch); // EMA 3 buffers
CopyBuffer(hiChimk[xs],0,0,barcalc,MITen); // Tenkan-sen buffers
CopyBuffer(hiChimk[xs],1,0,barcalc,MIKij); // Kijun-sen buffers
//--
bool risec=(MITen[0]<MIKij[0] && MAIch[2]<=MITen[2] && MAIch[1]>MITen[1]);
bool downc=(MITen[0]>MIKij[0] && MAIch[2]>=MITen[2] && MAIch[1]<MITen[1]);
//--
int dirmove=DirectionMove(symbol,TFt);
//--
if((exis==down) && (risec && dirmove==rise)) ret=rise;
if((exis==rise) && (downc && dirmove==down)) ret=down;
//--
return(ret);
//---
} //-end GetClosePosition()
//---------//
int MCEA::GetCloseInWeakSignal(const string symbol,int exis) // Signal Indicator Position Close in profit
{
//---
int ret=0;
int rise=1,
down=-1;
//--
if(exis==down && GetClosePosition(symbol,down)==rise) ret=rise;
if(exis==rise && GetClosePosition(symbol,rise)==down) ret=down;
//--
return(ret);
//---
} //-end GetCloseInWeakSignal()
//---------//
double MCEA::LotMartingale(const string symbol,double lotinit,double lastlot)
{
//---
double lotmart=0.0;
//--
double lotx1=NormalizeDouble(lotinit*Lotmpx[0],LotDig(symbol));
double lotx2=NormalizeDouble(lotx1*Lotmpx[1],LotDig(symbol));
double lotx3=NormalizeDouble(lotx1*Lotmpx[2],LotDig(symbol));
//--
if(lastlot>=lotx3) lotmart=lotinit;
else
if(lastlot>=lotx1 && lastlot<lotx2) lotmart=lotx2;
else
if(lastlot>=lotx2 && lastlot<lotx3) lotmart=lotx3;
else lotmart=lotx1;
//--
return(lotmart);
//---
} //-end LotMartingale()
//---------//
bool MCEA::OpenBuy(const string symbol)
{
//---
ResetLastError();
//--
bool buyopen = false;
string ldComm = GetCommentForOrder()+"_Buy";
double ldLot = MLots(symbol);
ENUM_ORDER_TYPE type_req = ORDER_TYPE_BUY;
//--
if(UseMartin==Yes)
{
int xs=PairsIdxArray(symbol);
if(CheckLastOrderIFLoss(symbol))
{
double lotmx=LotMartingale(symbol,ldLot,LastLotx[xs]);
if(lotmx>=ldLot)
{
ldLot=lotmx;
Do_Alerts(symbol,"Increase Lot size from = "+DoubleToString(LastLotx[xs],LotDig(symbol))+
" to = "+DoubleToString(ldLot,LotDig(symbol)));
}
}
}
//--
if(!GoodMarginTrade(symbol,type_req,ldLot,mc_symbol.Ask())) return(false);
//--
MqlTradeRequest req={};
MqlTradeResult res={};
MqlTradeCheckResult check={};
//-- structure is set to zero
ZeroMemory(req);
ZeroMemory(res);
ZeroMemory(check);
//--
CurrentSymbolSet(symbol);
double SL=OrderSLSet(symbol,type_req,mc_symbol.Bid());
double TP=OrderTPSet(symbol,type_req,mc_symbol.Ask());
//--
if(RefreshTick(symbol))
buyopen=mc_trade.Buy(ldLot,symbol,mc_symbol.Ask(),SL,TP,ldComm);
//--
int error=GetLastError();
if(buyopen||error==0)
{
string bsopen="Open BUY Order for "+symbol+" ~ Ticket= ["+(string)mc_trade.ResultOrder()+"] successfully..!";
Do_Alerts(symbol,bsopen);
int xi=PairsIdxArray(symbol);
PbarB[xi]=iTime(symbol,TFt,0);
}
else
{
mc_trade.CheckResult(check);
Do_Alerts(Symbol(),"Open BUY order for "+symbol+" FAILED!!. Return code= "+
(string)mc_trade.ResultRetcode()+". Code description: ["+mc_trade.ResultRetcodeDescription()+"]");
return(false);
}
//--
return(buyopen);
//--
//---
} //-end OpenBuy
//---------//
bool MCEA::OpenSell(const string symbol)
{
//---
ResetLastError();
//--
bool selopen = false;
string sdComm = GetCommentForOrder()+"_Sell";
double sdLot = MLots(symbol);
ENUM_ORDER_TYPE type_req = ORDER_TYPE_SELL;
//--
if(UseMartin==Yes)
{
int xs=PairsIdxArray(symbol);
if(CheckLastOrderIFLoss(symbol))
{
double lotmx=LotMartingale(symbol,sdLot,LastLotx[xs]);
if(lotmx>=sdLot) sdLot=lotmx;
Do_Alerts(symbol,"Increase Lot size from = "+DoubleToString(LastLotx[xs],LotDig(symbol))+
" to = "+DoubleToString(sdLot,LotDig(symbol)));
}
}
//--
if(!GoodMarginTrade(symbol,type_req,sdLot,mc_symbol.Ask())) return(false);
//--
MqlTradeRequest req={};
MqlTradeResult res={};
MqlTradeCheckResult check={};
//-- structure is set to zero
ZeroMemory(req);
ZeroMemory(res);
ZeroMemory(check);
//--
CurrentSymbolSet(symbol);
double SL=OrderSLSet(symbol,type_req,mc_symbol.Ask());
double TP=OrderTPSet(symbol,type_req,mc_symbol.Bid());
//--
if(RefreshTick(symbol))
selopen=mc_trade.Sell(sdLot,symbol,mc_symbol.Bid(),SL,TP,sdComm);
//--
int error=GetLastError();
if(selopen||error==0)
{
string bsopen="Open SELL Order for "+symbol+" ~ Ticket= ["+(string)mc_trade.ResultOrder()+"] successfully..!";
Do_Alerts(symbol,bsopen);
int xi=PairsIdxArray(symbol);
PbarS[xi]=iTime(symbol,TFt,0);
}
else
{
mc_trade.CheckResult(check);
Do_Alerts(Symbol(),"Open SELL order for "+symbol+" FAILED!!. Return code= "+
(string)mc_trade.ResultRetcode()+". Code description: ["+mc_trade.ResultRetcodeDescription()+"]");
return(false);
}
//--
return(selopen);
//--
//---
} //-end OpenSell
//---------//
double MCEA::OrderSLSet(const string xsymb,ENUM_ORDER_TYPE type,double atprice)
{
//---
slv=0.0;
int x=PairsIdxArray(xsymb);
Pips(xsymb);
RefreshTick(xsymb);
//--
switch(type)
{
case (ORDER_TYPE_BUY):
{
if(use_sl==Yes && autosl==Yes) slv=mc_symbol.NormalizePrice(atprice-38*pip);
else
if(use_sl==Yes && autosl==No) slv=mc_symbol.NormalizePrice(atprice-SLval*pip);
else slv=0.0;
//--
break;
}
case (ORDER_TYPE_SELL):
{
if(use_sl==Yes && autosl==Yes) slv=mc_symbol.NormalizePrice(atprice+38*pip);
else
if(use_sl==Yes && autosl==No) slv=mc_symbol.NormalizePrice(atprice+SLval*pip);
else slv=0.0;
}
}
//---
return(slv);
//---
} //-end OrderSLSet()
//---------//
double MCEA::OrderTPSet(const string xsymb,ENUM_ORDER_TYPE type,double atprice)
{
//---
tpv=0.0;
int x=PairsIdxArray(xsymb);
Pips(xsymb);
RefreshTick(xsymb);
//--
switch(type)
{
case (ORDER_TYPE_BUY):
{
if(use_tp==Yes && autotp==Yes) tpv=mc_symbol.NormalizePrice(atprice+50*pip);
else
if(use_tp==Yes && autotp==No) tpv=mc_symbol.NormalizePrice(atprice+TPval*pip);
else tpv=0.0;
//--
break;
}
case (ORDER_TYPE_SELL):
{
if(use_tp==Yes && autotp==Yes) tpv=mc_symbol.NormalizePrice(atprice-50*pip);
else
if(use_tp==Yes && autotp==No) tpv=mc_symbol.NormalizePrice(atprice-TPval*pip);
else tpv=0.0;
}
}
//---
return(tpv);
//---
} //-end OrderTPSet()
//---------//
void MCEA::CheckOpenPMx(const string symbx) //-- function: CheckOpenTrade.
{
//---
int totalorder=PositionsTotal();
xtto=totalorder;
//--
int xi=PairsIdxArray(symbx);
xob[xi]=0;
xos[xi]=0;
profitb[xi]=0.0;
profits[xi]=0.0;
double pos_profit = 0.0;
double pos_swap = 0.0;
double pos_comm = 0.0;
//--
for(int i=0; i<totalorder && !IsStopped(); i++)
{
string position_symbol=PositionGetSymbol(i);
long magic = mc_position.Magic();
if(position_symbol==symbx && magic==magicEA)
{
//--
ENUM_POSITION_TYPE opstype = mc_position.PositionType();
if(opstype == POSITION_TYPE_BUY)
{
xob[xi]++;
pos_profit = mc_position.Profit();
pos_swap = mc_position.Swap();
pos_comm = mc_position.Commission();
profitb[xi] += NormalizeDouble(pos_profit+pos_swap+pos_comm,2);
PbarB[xi] = iTime(symbx,TFt,0);
}
if(opstype == POSITION_TYPE_SELL)
{
xos[xi]++;
pos_profit = mc_position.Profit();
pos_swap = mc_position.Swap();
pos_comm = mc_position.Commission();
profits[xi] += NormalizeDouble(pos_profit+pos_swap+pos_comm,2);
PbarS[xi] = iTime(symbx,TFt,0);
}
//--
}
}
//---
return;
//---
} //-end CheckOpenPMx()
//---------//
bool MCEA::PartialCloseOrder(const string symbx)
{
//---
ResetLastError();
//--
double partClsB=0.0;
double partClsS=0.0;
bool partcls=false;
//--
int x=PairsIdxArray(symbx);
Pips(symbx);
//--
int total=PositionsTotal();
//--
for(int i=total-1; i>=0; i--)
{
string symbol=PositionGetSymbol(i);
if(symbol==symbx && mc_position.Magic()==magicEA)
{
ENUM_POSITION_TYPE opstype = mc_position.PositionType();
if(opstype==POSITION_TYPE_BUY)
{
RefreshTick(symbol);
double price = mc_position.PriceCurrent();
double pos_open = mc_position.PriceOpen();
double partClsB = pcbx[x]==0 ? mc_symbol.NormalizePrice(price-pos_open) : mc_symbol.NormalizePrice(price-pcbpos[x]);
double pos_vol = mc_position.Volume();
double part_vol = NormalizeDouble((pos_vol*(percentlots/100.0)),LotDig(symbx));
bool close_comp = (pos_vol-part_vol)<mc_symbol.LotsMin();
//--
double vol_close = pos_vol==mc_symbol.LotsMin() ? pos_vol : (pos_vol-part_vol)>mc_symbol.LotsMin() ?
part_vol : (pos_vol-part_vol)<mc_symbol.LotsMin() ? pos_vol : (pos_vol-mc_symbol.LotsMin());
vol_close=NormalizeDouble(vol_close,LotDig(symbx));
//--
bool closePartBuy = (partClsB>=(profitinpips*pip));
//--
if(closePartBuy) partcls=mc_trade.PositionClosePartial(symbx,vol_close,slip);
if(partcls)
{
pcbx[x]++;
pcbpos[x] = mc_symbol.NormalizePrice(price);
//--
string remvol=pos_vol-part_vol > 0.0 ? "\n ~ Remaining Vol: "+DoubleToString(pos_vol-part_vol,LotDig(symbx)) : "";
Do_Alerts(symbol, DoubleToString(percentlots,2)+ "% Volume Cut for "+symbx+" Success!"+remvol);
//--
Sleep(500);
RefreshTick(symbx);
bool modislb=false;
double modpossl=pcbx[x]==2 ? mc_symbol.NormalizePrice(pcbpos[x]-(profitinpips*pip)) : 0.0;
if(modpossl!=0.0) modislb=mc_trade.PositionModify(symbol,modpossl,mc_position.TakeProfit());
if(modislb)
Do_Alerts(symbol, "Modify SL at the previous volume cut position "+symbx+" "+DoubleToString(modpossl,dgts)+" Success!");
//--
if(close_comp)
{
pcbx[x]=0;
pcbpos[x]=0.0;
}
//--
break;
}
}
if(opstype==POSITION_TYPE_SELL)
{
RefreshTick(symbol);
double price = mc_position.PriceCurrent();
double pos_open = mc_position.PriceOpen();
double partClsS = pcsx[x]==0 ? mc_symbol.NormalizePrice(pos_open-price) : mc_symbol.NormalizePrice(pcspos[x]-price);
double pos_vol = mc_position.Volume();
double part_vol = NormalizeDouble((pos_vol*(percentlots/100.0)),LotDig(symbx));
bool close_comp = (pos_vol-part_vol)<mc_symbol.LotsMin();
//--
double vol_close = pos_vol==mc_symbol.LotsMin() ? pos_vol : (pos_vol-part_vol)>mc_symbol.LotsMin() ?
part_vol : (pos_vol-part_vol)<mc_symbol.LotsMin() ? pos_vol : (pos_vol-mc_symbol.LotsMin());
vol_close=NormalizeDouble(vol_close,LotDig(symbx));
//--
bool closePartSell = (partClsS>=(profitinpips*pip));
//--
if(closePartSell) partcls=mc_trade.PositionClosePartial(symbx,vol_close,slip);
if(partcls)
{
pcsx[x]++;
pcspos[x] = mc_symbol.NormalizePrice(price);
//--
string remvol=pos_vol-part_vol > 0.0 ? "\n ~ Remaining Vol: "+DoubleToString(pos_vol-part_vol,LotDig(symbx)) : "";
Do_Alerts(symbol, DoubleToString(percentlots,2)+ "% Volume Cut for "+symbx+" Success!"+remvol);
//--
Sleep(500);
RefreshTick(symbx);
bool modisls=false;
double modpossl=pcsx[x]==2 ? mc_symbol.NormalizePrice(pcspos[x]+(profitinpips*pip)) : 0.0;
if(modpossl!=0.0) modisls=mc_trade.PositionModify(symbol,modpossl,mc_position.TakeProfit());
if(modisls)
Do_Alerts(symbol, "Modify SL at the previous volume cut position "+symbx+" "+DoubleToString(modpossl,dgts)+" Success!");
//--
if(close_comp)
{
pcsx[x]=0;
pcspos[x]=0.0;
}
//--
break;
}
}
}
}
//--
return(partcls);
//---
} //-end PartialCloseOrder()
//---------//
double MCEA::TSPrice(const string xsymb,ENUM_POSITION_TYPE ptype,int TS_type)
{
//---
int br=2;
double pval=0.0;
int x=PairsIdxArray(xsymb);
Pips(xsymb);
//--
switch(TS_type)
{
case byprice:
{
RefreshTick(xsymb);
if(ptype==POSITION_TYPE_BUY) pval=mc_symbol.NormalizePrice(mc_symbol.Bid()-TSval*pip);
if(ptype==POSITION_TYPE_SELL) pval=mc_symbol.NormalizePrice(mc_symbol.Ask()+TSval*pip);
break;
}
case byindi:
{
double SMAML[];
ArrayResize(SMAML,br,br);
ArraySetAsSeries(SMAML,true);
CopyBuffer(hSMA20[x],0,0,br,SMAML);
RefreshPrice(xsymb,TFt,br);
//--
if(ptype==POSITION_TYPE_BUY && (SMAML[0]<mc_symbol.NormalizePrice(mc_symbol.Bid()-TSval*pip)))
pval=SMAML[0];
if(ptype==POSITION_TYPE_SELL && (SMAML[0]>mc_symbol.NormalizePrice(mc_symbol.Ask()+TSval*pip)))
pval=SMAML[0];
break;
}
case byHiLo:
{
UpdatePrice(xsymb,TFt,2);
//--
if(ptype==POSITION_TYPE_BUY && (HIGH[0]>HIGH[1]))
pval=LOW[1];
if(ptype==POSITION_TYPE_SELL && (LOW[0]<LOW[1]))
pval=HIGH[1];
break;
}
}
//--
return(pval);
//---
} //-end TSPrice()
//---------//
bool MCEA::ModifyOrdersSL(const string symbx,int TS_type)
{
//---
ResetLastError();
MqlTradeRequest req={};
MqlTradeResult res={};
MqlTradeCheckResult check={};
//--
int TRSP=TS_type;
bool modist=false;
int x=PairsIdxArray(symbx);
Pips(symbx);
//--
int total=PositionsTotal();
//--
for(int i=total-1; i>=0; i--)
{
string symbol=PositionGetSymbol(i);
if(symbol==symbx && mc_position.Magic()==magicEA)
{
ENUM_POSITION_TYPE opstype = mc_position.PositionType();
if(opstype==POSITION_TYPE_BUY)
{
RefreshTick(symbol);
double price = mc_position.PriceCurrent();
double vtrsb = mc_symbol.NormalizePrice(TSPrice(symbx,opstype,TRSP));
double pos_open = mc_position.PriceOpen();
double pos_stop = mc_position.StopLoss();
double pos_tp = mc_position.TakeProfit();
double pos_profit = mc_position.Profit();
double pos_swap = mc_position.Swap();
double pos_comm = mc_position.Commission();
double netp=pos_profit+pos_swap+pos_comm;
double modstart=mc_symbol.NormalizePrice(pos_open+TSmin*pip);
double modminsl=mc_symbol.NormalizePrice(vtrsb+((TSmin-1.0)*pip));
double modbuysl=vtrsb;
bool modbuy = (price>modminsl && modbuysl>modstart && (pos_stop==0.0||modbuysl>pos_stop));
//--
if(modbuy && netp>minprofit)
{
modist=mc_trade.PositionModify(symbol,modbuysl,pos_tp);
}
}
if(opstype==POSITION_TYPE_SELL)
{
RefreshTick(symbol);
double price = mc_position.PriceCurrent();
double vtrss = mc_symbol.NormalizePrice(TSPrice(symbx,opstype,TRSP));
double pos_open = mc_position.PriceOpen();
double pos_stop = mc_position.StopLoss();
double pos_tp = mc_position.TakeProfit();
double pos_profit = mc_position.Profit();
double pos_swap = mc_position.Swap();
double pos_comm = mc_position.Commission();
double netp=pos_profit+pos_swap+pos_comm;
double modstart=mc_symbol.NormalizePrice(pos_open-TSmin*pip);
double modminsl=mc_symbol.NormalizePrice(vtrss-((TSmin+1.0)*pip));
double modselsl=vtrss;
bool modsel = (price<modminsl && modselsl<modstart && (pos_stop==0.0||modselsl<pos_stop));
//--
if(modsel && netp>minprofit)
{
modist=mc_trade.PositionModify(symbol,modselsl,pos_tp);
}
}
}
}
//--
return(modist);
//---
} //-end ModifyOrdersSL()
//---------//
bool MCEA::ModifyOrdersTP(const string symbx)
{
//---
ResetLastError();
MqlTradeRequest req={};
MqlTradeResult res={};
MqlTradeCheckResult check={};
//--
bool modist=false;
int x=PairsIdxArray(symbx);
Pips(symbx);
//--
int total=PositionsTotal();
//--
for(int i=total-1; i>=0; i--)
{
string symbol=PositionGetSymbol(i);
if(symbol==symbx && mc_position.Magic()==magicEA)
{
ENUM_POSITION_TYPE opstype = mc_position.PositionType();
if(opstype==POSITION_TYPE_BUY)
{
RefreshTick(symbol);
double price = mc_position.PriceCurrent();
double pos_open = mc_position.PriceOpen();
double pos_stop = mc_position.StopLoss();
double pos_tp = mc_position.TakeProfit();
double modbuytp = pos_tp==0.0 ? mc_symbol.NormalizePrice(pos_open+TPmin*pip) : pos_tp;
double modpostp = mc_symbol.NormalizePrice(price+TPmin*pip);
bool modtpb = (price>pos_open && modbuytp-price<TPmin*pip && pos_tp<modpostp);
//--
if(modtpb)
{
modist=mc_trade.PositionModify(symbol,pos_stop,modpostp);
}
}
if(opstype==POSITION_TYPE_SELL)
{
RefreshTick(symbol);
double price = mc_position.PriceCurrent();
double pos_open = mc_position.PriceOpen();
double pos_stop = mc_position.StopLoss();
double pos_tp = mc_position.TakeProfit();
double modseltp = pos_tp==0.0 ? mc_symbol.NormalizePrice(pos_open-TPmin*pip) : pos_tp;
double modpostp = mc_symbol.NormalizePrice(price-TPmin*pip);
bool modtps = (price<pos_open && price-modseltp<TPmin*pip && pos_tp>modpostp);
//--
if(modtps)
{
modist=mc_trade.PositionModify(symbol,pos_stop,modpostp);
}
}
}
}
//--
return(modist);
//---
} //-end ModifyOrdersTP()
//---------//
void MCEA::SetSLTPOrders(void)
{
//---
ResetLastError();
MqlTradeRequest req={};
MqlTradeResult res={};
MqlTradeCheckResult check={};
//--
double modbuysl=0;
double modselsl=0;
double modbuytp=0;
double modseltp=0;
string position_symbol;
int totalorder=PositionsTotal();
//--
for(int i=totalorder-1; i>=0; i--)
{
string symbol=PositionGetSymbol(i);
position_symbol=symbol;
if(mc_position.Magic()==magicEA)
{
ENUM_POSITION_TYPE opstype = mc_position.PositionType();
if(opstype==POSITION_TYPE_BUY)
{
Pips(symbol);
RefreshTick(symbol);
double price = mc_position.PriceCurrent();
double pos_open = mc_position.PriceOpen();
double pos_stop = mc_position.StopLoss();
double pos_take = mc_position.TakeProfit();
modbuysl=SetOrderSL(symbol,opstype,pos_open);
if(price<modbuysl) modbuysl=mc_symbol.NormalizePrice(price-slip*pip);
modbuytp=SetOrderTP(symbol,opstype,pos_open);
if(price>modbuytp) modbuytp=mc_symbol.NormalizePrice(price+slip*pip);
//--
if(pos_stop==0.0 || pos_take==0.0)
{
if(!mc_trade.PositionModify(position_symbol,modbuysl,modbuytp))
{
mc_trade.CheckResult(check);
Do_Alerts(symbol,"Set SL and TP for "+EnumToString(opstype)+" on "+symbol+" FAILED!!. Return code= "+
(string)mc_trade.ResultRetcode()+". Code description: ["+mc_trade.ResultRetcodeDescription()+"]");
}
}
}
if(opstype==POSITION_TYPE_SELL)
{
Pips(symbol);
RefreshTick(symbol);
double price = mc_position.PriceCurrent();
double pos_open = mc_position.PriceOpen();
double pos_stop = mc_position.StopLoss();
double pos_take = mc_position.TakeProfit();
modselsl=SetOrderSL(symbol,opstype,pos_open);
if(price>modselsl) modselsl=mc_symbol.NormalizePrice(price+slip*pip);
modseltp=SetOrderTP(symbol,opstype,pos_open);
if(price<modseltp) modseltp=mc_symbol.NormalizePrice(price-slip*pip);
//--
if(pos_stop==0.0 || pos_take==0.0)
{
if(!mc_trade.PositionModify(position_symbol,modselsl,modseltp))
{
mc_trade.CheckResult(check);
Do_Alerts(symbol,"Set SL and TP for "+EnumToString(opstype)+" on "+symbol+" FAILED!!. Return code= "+
(string)mc_trade.ResultRetcode()+". Code description: ["+mc_trade.ResultRetcodeDescription()+"]");
}
}
}
}
}
//--
return;
//---
} //-end SetSLTPOrders
//---------//
double MCEA::SetOrderSL(const string xsymb,ENUM_POSITION_TYPE type,double atprice)
{
//---
slv=0.0;
int x=PairsIdxArray(xsymb);
Pips(xsymb);
RefreshTick(xsymb);
//--
switch(type)
{
case (POSITION_TYPE_BUY):
{
slv=mc_symbol.NormalizePrice(atprice-SLval*pip);
//--
break;
}
case (POSITION_TYPE_SELL):
{
slv=mc_symbol.NormalizePrice(atprice+SLval*pip);
//--
break;
}
}
//---
return(slv);
//---
} //-end SetOrderSL()
//---------//
double MCEA::SetOrderTP(const string xsymb,ENUM_POSITION_TYPE type,double atprice)
{
//---
tpv=0.0;
int x=PairsIdxArray(xsymb);
Pips(xsymb);
RefreshTick(xsymb);
//--
switch(type)
{
case (POSITION_TYPE_BUY):
{
tpv=mc_symbol.NormalizePrice(atprice+TPval*pip);
//--
break;
}
case (POSITION_TYPE_SELL):
{
tpv=mc_symbol.NormalizePrice(atprice-TPval*pip);
}
}
//---
return(tpv);
//---
} //-end SetOrderTP()
//---------//
bool MCEA::CloseBuyPositions(const string symbol)
{
//---
//--
ResetLastError();
bool buyclose=false;
int total=PositionsTotal(); // number of open positions
ENUM_POSITION_TYPE closetype = POSITION_TYPE_BUY;
ENUM_ORDER_TYPE type_req = ORDER_TYPE_SELL;
//--
MqlTradeRequest req={};
MqlTradeResult res={};
MqlTradeCheckResult check={};
//--
int x=PairsIdxArray(symbol);
//--- iterate over all open positions
for(int i=total-1; i>=0; i--)
{
if(mc_position.SelectByIndex(i))
{
//--- Parameters of the order
string position_Symbol = PositionGetSymbol(i);
ulong position_ticket = PositionGetTicket(i);
ENUM_POSITION_TYPE type = mc_position.PositionType();
//--- if the MagicNumber matches
if((position_Symbol==symbol) && (mc_position.Magic()==magicEA))
{
//--
if(type==closetype)
{
RefreshTick(position_Symbol);
buyclose=mc_trade.PositionClose(position_Symbol,slip);
//--- output information about the closure
PrintFormat("Close Buy #%I64d %s %s",position_ticket,position_Symbol,EnumToString(type));
if(buyclose) PbarB[x]=iTime(symbol,TFt,0);
}
}
}
}
//---
return(buyclose);
//----
} //-end CloseBuyPositions()
//---------//
bool MCEA::CloseSellPositions(const string symbol)
{
//---
ResetLastError();
bool sellclose=false;
int total=PositionsTotal(); // number of open positions
ENUM_POSITION_TYPE closetype = POSITION_TYPE_SELL;
ENUM_ORDER_TYPE type_req = ORDER_TYPE_BUY;
//--
MqlTradeRequest req={};
MqlTradeResult res={};
MqlTradeCheckResult check={};
//--
int x=PairsIdxArray(symbol);
//--- iterate over all open positions
for(int i=total-1; i>=0; i--)
{
if(mc_position.SelectByIndex(i))
{
//--- Parameters of the order
string position_Symbol = PositionGetSymbol(i);
ulong position_ticket = PositionGetTicket(i);
ENUM_POSITION_TYPE type = mc_position.PositionType();
//--- if the MagicNumber matches
if((position_Symbol==symbol) && (mc_position.Magic()==magicEA))
{
//--
if(type==closetype)
{
RefreshTick(position_Symbol);
sellclose=mc_trade.PositionClose(position_Symbol,slip);
//--- output information about the closure
PrintFormat("Close Sell #%I64d %s %s",position_ticket,position_Symbol,EnumToString(type));
if(sellclose) PbarS[x]=iTime(symbol,TFt,0);
}
}
}
}
//---
return(sellclose);
//----
} //-end CloseSellPositions()
//---------//
bool MCEA::CloseAllLoss(void)
{
//----
ResetLastError();
//--
bool orclose=false;
string isloss="due stop in loss.";
//--
MqlTradeRequest req={};
MqlTradeResult res={};
MqlTradeCheckResult check={};
//--
int ttlorder=PositionsTotal(); // number of open positions
//--
for(int x=0; x<arrsymbx; x++)
{
string symbol=DIRI[x];
Pips(symbol);
double posloss=mc_symbol.NormalizePrice(SLval*pip);
orclose=false;
//--
for(int i=ttlorder-1; i>=0; i--)
{
string position_Symbol = PositionGetSymbol(i);
ENUM_POSITION_TYPE type = mc_position.PositionType();
if((position_Symbol==symbol) && (mc_position.Magic()==magicEA))
{
double price = mc_position.PriceCurrent();
double pos_open = mc_position.PriceOpen();
double posloss = mc_symbol.NormalizePrice(SLval*pip);
double pricegab = mc_symbol.NormalizePrice(fabs(price-pos_open));
ulong position_ticket = PositionGetTicket(i);
//---
if(type==POSITION_TYPE_BUY && pricegab>posloss)
{
RefreshTick(position_Symbol);
orclose = mc_trade.PositionClose(position_Symbol,slip);
//--- output information about the closure
PrintFormat("Close Buy %s %s %s",symbol,EnumToString(POSITION_TYPE_BUY),isloss);
}
if(type==POSITION_TYPE_SELL && pricegab>posloss)
{
RefreshTick(position_Symbol);
orclose = mc_trade.PositionClose(position_Symbol,slip);
//--- output information about the closure
PrintFormat("Close Sell %s %s %s",symbol,EnumToString(POSITION_TYPE_BUY),isloss);
}
}
}
}
//--
return(orclose);
//----
} //-end CloseAllLoss()
//---------//
bool MCEA::CloseAllProfit(void)
{
//----
ResetLastError();
//--
bool orclose=false;
//--
MqlTradeRequest req={};
MqlTradeResult res={};
MqlTradeCheckResult check={};
//--
int ttlorder=PositionsTotal(); // number of open positions
//--
for(int x=0; x<arrsymbx; x++)
{
string symbol=DIRI[x];
orclose=false;
//--
for(int i=ttlorder-1; i>=0; i--)
{
string position_Symbol = PositionGetSymbol(i);
ENUM_POSITION_TYPE type = mc_position.PositionType();
if((position_Symbol==symbol) && (mc_position.Magic()==magicEA))
{
double pos_profit = mc_position.Profit();
double pos_swap = mc_position.Swap();
double pos_comm = mc_position.Commission();
double cur_profit = NormalizeDouble(pos_profit+pos_swap+pos_comm,2);
ulong position_ticket = PositionGetTicket(i);
//---
if(type==POSITION_TYPE_BUY && cur_profit>minprofit)
{
RefreshTick(position_Symbol);
orclose = mc_trade.PositionClose(position_Symbol,slip);
//--- output information about the closure
PrintFormat("Close #%I64d %s %s",position_ticket,position_Symbol,EnumToString(type));
if(orclose) PbarB[x]=iTime(symbol,TFt,0);
}
if(type==POSITION_TYPE_SELL && cur_profit>minprofit)
{
RefreshTick(position_Symbol);
orclose = mc_trade.PositionClose(position_Symbol,slip);
//--- output information about the closure
PrintFormat("Close #%I64d %s %s",position_ticket,position_Symbol,EnumToString(type));
if(orclose) PbarS[x]=iTime(symbol,TFt,0);
}
}
}
}
//--
return(orclose);
//----
} //-end CloseAllProfit()
//---------//
bool MCEA::ManualCloseAllProfit(void)
{
//----
ResetLastError();
//--
bool orclose=false;
//--
MqlTradeRequest req={};
MqlTradeResult res={};
MqlTradeCheckResult check={};
//--
int ttlorder=PositionsTotal(); // number of open positions
//--
for(int x=0; x<arrsymbx; x++)
{
string symbol=DIRI[x];
orclose=false;
//--
for(int i=ttlorder-1; i>=0; i--)
{
string position_Symbol = PositionGetSymbol(i);
ENUM_POSITION_TYPE type = mc_position.PositionType();
if((position_Symbol==symbol) && (mc_position.Magic()==magicEA))
{
double pos_profit = mc_position.Profit();
double pos_swap = mc_position.Swap();
double pos_comm = mc_position.Commission();
double cur_profit = NormalizeDouble(pos_profit+pos_swap+pos_comm,2);
ulong position_ticket = PositionGetTicket(i);
//---
if(type==POSITION_TYPE_BUY && cur_profit>0.02)
{
RefreshTick(position_Symbol);
orclose = mc_trade.PositionClose(position_Symbol,slip);
//--- output information about the closure
PrintFormat("Close #%I64d %s %s",position_ticket,position_Symbol,EnumToString(type));
if(orclose) PbarB[x]=iTime(symbol,TFt,0);
}
if(type==POSITION_TYPE_SELL && cur_profit>0.02)
{
RefreshTick(position_Symbol);
orclose = mc_trade.PositionClose(position_Symbol,slip);
//--- output information about the closure
PrintFormat("Close #%I64d %s %s",position_ticket,position_Symbol,EnumToString(type));
if(orclose) PbarS[x]=iTime(symbol,TFt,0);
}
}
}
}
//--
return(orclose);
//----
} //-end ManualCloseAllProfit()
//---------//
bool MCEA::CheckProfit(const string symbol,ENUM_POSITION_TYPE intype)
{
//---
Pips(symbol);
double posprofit=mc_symbol.NormalizePrice((TPval*0.5)*pip);
bool inprofit=false;
//--
int ttlorder=PositionsTotal(); // number of open positions
//--
for(int x=0; x<arrsymbx; x++)
{
string symbol=DIRI[x];
//--
for(int i=ttlorder-1; i>=0; i--)
{
string position_Symbol = PositionGetSymbol(i);
ENUM_POSITION_TYPE type = mc_position.PositionType();
if((position_Symbol==symbol) && (mc_position.Magic()==magicEA))
{
double price = mc_position.PriceCurrent();
double pos_open = mc_position.PriceOpen();
double posprofit = mc_symbol.NormalizePrice((TPval*0.5)*pip);
double pricegab = mc_symbol.NormalizePrice(fabs(price-pos_open));
//---
if(type==intype && posprofit<pricegab) inprofit=true;
}
}
}
//--
return(inprofit);
//----
} //-end CheckProfit()
//---------//
bool MCEA::CheckLoss(const string symbol,ENUM_POSITION_TYPE intype,double slc=0.0)
{
//---
Pips(symbol);
bool inloss=false;
double lossval=slc==0.0 ? (SLval*0.5) : slc;
double posloss = mc_symbol.NormalizePrice(slc*pip);
int ttlorder=PositionsTotal(); // number of open positions
//--
for(int x=0; x<arrsymbx; x++)
{
string symbol=DIRI[x];
//--
for(int i=ttlorder-1; i>=0; i--)
{
string position_Symbol = PositionGetSymbol(i);
ENUM_POSITION_TYPE type = mc_position.PositionType();
if((position_Symbol==symbol) && (mc_position.Magic()==magicEA))
{
double price = mc_position.PriceCurrent();
double pos_open = mc_position.PriceOpen();
double posloss = mc_symbol.NormalizePrice(lossval*pip);
double pricegab = mc_symbol.NormalizePrice(fabs(price-pos_open));
//---
if(type==intype && pricegab>posloss) inloss=true;
}
}
}
//--
return(inloss);
//----
} //-end CheckLoss()
//---------//
bool MCEA::CheckProfitLoss(const string symbol)
{
//----
ResetLastError();
//--
bool closeinloss=false;
string isloss="due stop in loss.";
//--
int xx=PairsIdxArray(symbol);
//--
bool BuyProfitSellLoss=(xob[xx]>0 && CheckProfit(symbol,POSITION_TYPE_BUY)) && (xos[xx]>0 && CheckLoss(symbol,POSITION_TYPE_SELL,0.0));
bool SellProfitBuyLoss=(xos[xx]>0 && CheckProfit(symbol,POSITION_TYPE_SELL)) && (xob[xx]>0 && CheckLoss(symbol,POSITION_TYPE_BUY,0.0));
//--
if(BuyProfitSellLoss && !SellProfitBuyLoss)
{
if(CloseSellPositions(symbol))
{
PrintFormat("Close Sell %s %s %s",symbol,EnumToString(POSITION_TYPE_BUY),isloss);
closeinloss=true;
}
}
if(SellProfitBuyLoss && !BuyProfitSellLoss)
{
if(CloseBuyPositions(symbol))
{
PrintFormat("Close Buy %s %s %s",symbol,EnumToString(POSITION_TYPE_SELL),isloss);
closeinloss=true;
}
}
//--
return(closeinloss);
//----
} //-end CheckProfitLoss()
//---------//
void MCEA::CloseAllOrders(void) //-- function: close all order
{
//----
ResetLastError();
//--
MqlTradeRequest req={};
MqlTradeResult res={};
MqlTradeCheckResult check={};
//--
int total=PositionsTotal(); // number of open positions
//--- iterate over all open positions
for(int i=total-1; i>=0; i--)
{
//--- if the MagicNumber matches
if(mc_position.Magic()==magicEA)
{
//--
string position_Symbol = PositionGetSymbol(i); // symbol of the position
ulong position_ticket = PositionGetTicket(i); // ticket of the the opposite position
ENUM_POSITION_TYPE type = mc_position.PositionType();
RefreshTick(position_Symbol);
bool closepos = mc_trade.PositionClose(position_Symbol,slip);
if(closepos && type==POSITION_TYPE_BUY) PbarB[i]=iTime(position_Symbol,TFt,0);
if(closepos && type==POSITION_TYPE_SELL) PbarS[i]=iTime(position_Symbol,TFt,0);
//--- output information about the closure
PrintFormat("Close #%I64d %s %s",position_ticket,position_Symbol,EnumToString(type));
//---
}
}
//---
return;
//----
} //-end CloseAllOrders()
//---------//
void MCEA::CheckClose(const string symbx)
{
//---
//--
ResetLastError();
Pips(symbx);
//--
datetime to=TimeCurrent();
datetime from=to-(60);
closetime=TimeCurrent()-(3); // 3 seconds ago
//--- request the entire history
HistorySelect(from,to);
//--- total number in the list of deals
int deals=HistoryDealsTotal();
//--
datetime deal_time =0; // time of a deal execution
ulong deal_ticket =0; // deal ticket
long deal_magic =0; // deal magic number
long deal_type =0; // Order Type
double deal_price =0.0; // deal/order CLOSE price
double deal_profit =0.0; // deal profit
double deal_swap =0.0; // position swap
double deal_comm =0.0; // position commission
string deal_symbol =""; // symbol of the deal
ENUM_DEAL_ENTRY deal_entry =0; // enum deal entry
double profit_loss =0.0; // Order profit or loss
//--
//--- go through deals in a loop
for(int z=deals-1; z>=0 && !IsStopped(); z--)
{
deal_ticket = HistoryDealGetTicket(z);
deal_symbol = HistoryDealGetString(deal_ticket,DEAL_SYMBOL);
deal_magic = HistoryDealGetInteger(deal_ticket,DEAL_MAGIC);
deal_entry = (ENUM_DEAL_ENTRY)HistoryDealGetInteger(deal_ticket,DEAL_ENTRY);
deal_type = (ENUM_DEAL_TYPE)HistoryDealGetInteger(deal_ticket,DEAL_TYPE);
//--
if(deal_symbol==symbx && deal_magic==magicEA)
{
if((deal_entry==DEAL_ENTRY_OUT)||(deal_entry==DEAL_ENTRY_OUT_BY))
{
deal_time = (datetime)HistoryDealGetInteger(deal_ticket,DEAL_TIME);
if((deal_time>0) && (deal_time>=closetime))
{
deal_price = HistoryDealGetDouble(deal_ticket,DEAL_PRICE);
deal_profit = HistoryDealGetDouble(deal_ticket,DEAL_PROFIT);
deal_swap = HistoryDealGetDouble(deal_ticket,DEAL_SWAP);
deal_comm = HistoryDealGetDouble(deal_ticket,DEAL_COMMISSION);
profit_loss = NormalizeDouble(deal_profit+deal_swap+deal_comm,2);
string xtype = deal_type==DEAL_TYPE_BUY ? "SELL" : deal_type==DEAL_TYPE_SELL ? "BUY": "";
//--
if(profit_loss>0)
{
string ckclose="Close "+xtype+" Position on "+symbx+" at price : "+DoubleToString(deal_price,dgts)+
" OrderCloseTime(): "+TimeToString(deal_time,TIME_DATE|TIME_MINUTES)+
" in profit : "+DoubleToString(profit_loss,2);
Do_Alerts(symbx,ckclose);
}
if(profit_loss<=0)
{
string ckclose="Close "+xtype+" Position on "+symbx+" at price : "+DoubleToString(deal_price,dgts)+
" OrderCloseTime(): "+TimeToString(deal_time,TIME_DATE|TIME_MINUTES)+
" in loss : "+DoubleToString(profit_loss,2);
Do_Alerts(symbx,ckclose);
}
//--
break;
}
}
}
}
//---
return;
//----
} //-end CheckClose()
//---------//
bool MCEA::CheckLastOrderIFLoss(const string symbx)
{
//---
bool LOloss=false;
//--
ResetLastError();
int xs=PairsIdxArray(symbx);
LastLotx[xs]=0.0;
//--
datetime from=StringToTime(ReqDate(ThisTime(day),0,0));
datetime to=TimeCurrent();
//--- request the entire history
HistorySelect(from,to);
//--- total number in the list of deals
int deals=HistoryDealsTotal();
//--
datetime deal_time =0; // time of a deal execution
ulong deal_ticket =0; // deal ticket
long deal_magic =0; // deal magic number
long deal_type =0; // Order Type
double deal_profit =0.0; // deal profit
double deal_swap =0.0; // position swap
double deal_comm =0.0; // position commission
double deal_volume =0.0; // deal volume
string deal_symbol =""; // symbol of the deal
ENUM_DEAL_ENTRY deal_entry =0; // enum deal entry
double profit_loss =0.0; // Order profit or loss
//--
//--- go through deals in a loop
for(int z=deals-1; z>=0 && !IsStopped(); z--)
{
deal_ticket = HistoryDealGetTicket(z);
deal_symbol = HistoryDealGetString(deal_ticket,DEAL_SYMBOL);
deal_magic = HistoryDealGetInteger(deal_ticket,DEAL_MAGIC);
deal_entry = (ENUM_DEAL_ENTRY)HistoryDealGetInteger(deal_ticket,DEAL_ENTRY);
deal_type = (ENUM_DEAL_TYPE)HistoryDealGetInteger(deal_ticket,DEAL_TYPE);
//--
if(deal_symbol==symbx && deal_magic==magicEA)
{
if((deal_entry==DEAL_ENTRY_OUT)||(deal_entry==DEAL_ENTRY_OUT_BY))
{
deal_time = (datetime)HistoryDealGetInteger(deal_ticket,DEAL_TIME);
if((deal_time>0) && (deal_time>=closetime))
{
deal_volume = HistoryDealGetDouble(deal_ticket,DEAL_VOLUME);
deal_profit = HistoryDealGetDouble(deal_ticket,DEAL_PROFIT);
deal_swap = HistoryDealGetDouble(deal_ticket,DEAL_SWAP);
deal_comm = HistoryDealGetDouble(deal_ticket,DEAL_COMMISSION);
profit_loss = NormalizeDouble(deal_profit+deal_swap+deal_comm,2);
//--
if(profit_loss<=0.0)
{
LastLotx[xs] = deal_volume;
LOloss = true;
}
//--
break;
}
}
}
}
//---
return(LOloss);
//----
} //-end CheckLastOrderIFLoss()
//---------//
void MCEA::TodayOrders(void)
{
//---
//--
ResetLastError();
//--
datetime from=StringToTime(ReqDate(ThisTime(day),0,0));
datetime to=TimeCurrent();
//--- request the entire history
HistorySelect(from,to);
//--- total number in the list of deals
int deals=HistoryDealsTotal();
//--
datetime deal_time =0; // time of a deal execution
ulong deal_ticket =0; // deal ticket
long deal_magic =0; // deal magic number
long deal_type =0; // Order Type
double deal_price =0.0; // deal/order CLOSE price
double deal_profit =0.0; // deal profit
double deal_swap =0.0; // position swap
double deal_comm =0.0; // position commission
ENUM_DEAL_ENTRY deal_entry =0; // enum deal entry
//--
string pos_symbol =""; // Position symbol
fixclprofit =0.0; // Order Close profit
floatprofit =0.0; // float position profit
oBm=0; // Order buy
oSm=0; // Order sell
//--
int totalorder=PositionsTotal();
//--
for(int i=0; i<totalorder && !IsStopped(); i++)
{
pos_symbol = PositionGetSymbol(i);
long magic = mc_position.Magic();
if(mc_position.Symbol() == pos_symbol && magic==magicEA)
{
//--
ENUM_POSITION_TYPE opstype = mc_position.PositionType();
if(opstype == POSITION_TYPE_BUY) {oBm++; floatprofit += mc_position.Profit();}
if(opstype == POSITION_TYPE_SELL) {oSm++; floatprofit += mc_position.Profit();}
//--
}
}
xtto=oBm+oSm;
//--
//--- go through deals in a loop
for(int z=0; z<deals && !IsStopped(); z++)
{
deal_ticket = HistoryDealGetTicket(z);
deal_magic = HistoryDealGetInteger(deal_ticket,DEAL_MAGIC);
deal_entry = (ENUM_DEAL_ENTRY)HistoryDealGetInteger(deal_ticket,DEAL_ENTRY);
deal_type = (ENUM_DEAL_TYPE)HistoryDealGetInteger(deal_ticket,DEAL_TYPE);
if(deal_magic==magicEA)
{
if((deal_entry==DEAL_ENTRY_OUT)||(deal_entry==DEAL_ENTRY_OUT_BY))
{
deal_time = (datetime)HistoryDealGetInteger(deal_ticket,DEAL_TIME);
//--
if((deal_time>0) && (deal_time>=from))
{
deal_profit = HistoryDealGetDouble(deal_ticket,DEAL_PROFIT);
deal_swap = HistoryDealGetDouble(deal_ticket,DEAL_SWAP);
deal_comm = HistoryDealGetDouble(deal_ticket,DEAL_COMMISSION);
//--
fixclprofit += NormalizeDouble(deal_profit+deal_swap+deal_comm,2);
}
}
}
}
//---
return;
//----
} //-end TodayOrders()
//---------//
double MCEA::MLots(const string symbx) // function: calculation lots size
{
//----
double Lsize=0.0;
double sym_Lm=0.0;
string sym_use ="";
int pil;
int Lpair;
int xsym=-1;
//--
string sCur1=StringSubstr(symbx,posCur1,3);
string sCur2=StringSubstr(symbx,posCur2,3);
//--
if(sCur1=="EUR"||sCur1=="GBP"||sCur1=="AUD"||sCur1=="NZD") pil=0;
if(sCur1=="CAD"||sCur1=="CHF") pil=1;
if(sCur1=="XAU"||sCur1=="XAG") pil=2;
if(sCur1=="USD") pil=3;
//--
switch(pil)
{
case 0: sym_use=sCur1+"USD"; break;
case 1: sym_use="USD"+sCur1; break;
case 2: sym_use=symbx; break;
case 3: sym_use=symbx; break;
}
//--
xsym=PairsIdxArray(sym_use);
if(xsym!=-1) sym_use=DIRI[xsym];
Lpair = StringFind(sym_use,"USD",0);
//--
CurrentSymbolSet(sym_use);
double csize = mc_symbol.ContractSize();
double AFMar = mc_account.FreeMargin();
double AFLev = (double)mc_account.Leverage();
double symbid = mc_symbol.Bid();
//--
double Lmaxs = SymbolInfoDouble(symbx,SYMBOL_VOLUME_MAX);
double Lmins = SymbolInfoDouble(symbx,SYMBOL_VOLUME_MIN);
//--
double useRisk = (Risk/100.0);
double PctUse = ((100.0-Risk)/100.0);
//--
double NZ1=NonZeroDiv(AFMar*AFLev,csize);
double NZ2=NonZeroDiv(AFMar*AFLev,symbid);
//--
if(Lpair>=0 && Lpair<posCur2) {sym_Lm = fmin(Lmaxs,NZ1);}
else {sym_Lm = fmin(Lmaxs,NonZeroDiv(NZ2,csize));}
//--
double sym_Lc = NormalizeDouble(sym_Lm*useRisk,LotDig(symbx));
double asize = NormalizeDouble(sym_Lc/(double)LotPS,LotDig(symbx));
//--
if(mmlot==DynamLot)
{
Lsize = NormalizeDouble(asize*PctUse,LotDig(symbx));
}
else {Lsize = Lots;}
//--
if(Lsize < Lmins) Lsize = Lmins;
if(Lsize > Lmaxs) Lsize = Lmaxs;
//--
double lotsize=NormalizeDouble(Lsize,LotDig(symbx));
//--
return(lotsize);
//----
} //-end MLots()
//---------//
int MCEA::LotDig(const string symbx)
{
//---
double lots_step=SymbolInfoDouble(symbx,SYMBOL_VOLUME_STEP);
//--
if(lots_step==0.01)
ldig=2;
//--
if(lots_step==0.1)
ldig=1;
//--
if(lots_step==1.0)
ldig=0;
//---
return(ldig);
//----
} //-end LotDig()
//---------//
double MCEA::NonZeroDiv(double val1,double val2)
{
//---
double resval=0.0;
if(val1==0.0 || val2==0.0) resval=0.00;
else
resval=val1/val2;
//--
return(resval);
//---
} //-end NonZeroDiv()
//---------//
bool MCEA::CheckEquityBalance(void)
{
//---
bool isgood=false;
if((mc_account.Equity()/mc_account.Balance()*100) > (100.00-Risk)) isgood=true;
//--
return(isgood);
//---
} //-end CheckEquityBalance()
//---------//
void MCEA::TradeInfo(void) // function: write comments on the chart
{
//----
Pips(Symbol());
double spread=SymbolInfoInteger(Symbol(),SYMBOL_SPREAD)/xpip;
rem=zntm-TimeCurrent();
string postime=PosTimeZone();
string eawait=" - Waiting for active time..!";
//--
string comm="";
TodayOrders();
//--
comm="\n :: Server Date Time : "+string(ThisTime(year))+"."+string(ThisTime(mon))+"."+string(ThisTime(day))+ " "+TimeToString(TimeCurrent(),TIME_SECONDS)+
"\n ------------------------------------------------------------"+
"\n :: Broker : "+ TerminalInfoString(TERMINAL_COMPANY)+
"\n :: Expert Name : "+ expname+
"\n :: Acc. Name : "+ mc_account.Name()+
"\n :: Acc. Number : "+ (string)mc_account.Login()+
"\n :: Acc. TradeMode : "+ AccountMode()+
"\n :: Acc. Leverage : 1 : "+ (string)mc_account.Leverage()+
"\n :: Acc. Equity : "+ DoubleToString(mc_account.Equity(),2)+
"\n :: Margin Mode : "+ (string)mc_account.MarginModeDescription()+
"\n :: Magic Number : "+ string(magicEA)+
"\n :: Trade on TF : "+ EnumToString(TFt)+
"\n :: Today Trading : "+ TradingDay()+" : "+hariini+
"\n :: Trading Session : "+ tz_ses+
"\n :: Trading Time : "+ postime;
if(TimeCurrent()<zntm)
{
comm=comm+
"\n :: Time Remaining : "+(string)ReqTime(rem,hour)+":"+(string)ReqTime(rem,min)+":"+(string)ReqTime(rem,sec) + eawait;
}
comm=comm+
"\n ------------------------------------------------------------"+
"\n :: Trading Pairs : "+pairs+
"\n :: BUY Market : "+string(oBm)+
"\n :: SELL Market : "+string(oSm)+
"\n :: Total Order : "+string(oBm+oSm)+
"\n :: Order Profit : "+DoubleToString(floatprofit,2)+
"\n :: Fixed Profit : "+DoubleToString(fixclprofit,2)+
"\n :: Float Money : "+DoubleToString(floatprofit,2)+
"\n :: Nett Profit : "+DoubleToString(floatprofit+fixclprofit,2);
//--
Comment(comm);
ChartRedraw(0);
return;
//----
} //-end TradeInfo()
//---------//
string MCEA::PosTimeZone(void)
{
//---
string tzpos="";
//--
if(ReqTime(zntm,day)>ThisTime(day))
{
tzpos=tz_opn+ " Next day to " +tz_cls + " Next day";
}
else
if(TimeCurrent()<znop)
{
if(ThisTime(day)==ReqTime(znop,day) && ThisTime(day)==ReqTime(zncl,day))
tzpos=tz_opn+" to " +tz_cls+ " Today";
//else
if(ThisTime(day)==ReqTime(znop,day) && ThisTime(day)<ReqTime(zncl,day))
tzpos=tz_opn+ " Today to " +tz_cls+ " Next day";
}
else
if(TimeCurrent()>=znop && TimeCurrent()<zncl)
{
if(ThisTime(day)<ReqTime(zncl,day))
tzpos=tz_opn+ " Today to " +tz_cls+ " Next day";
else
if(ThisTime(day)==ReqTime(zncl,day))
tzpos=tz_opn+" to " +tz_cls+ " Today";
}
else
if(ThisTime(day)==ReqTime(znop,day) && ThisTime(day)<ReqTime(zncl,day))
{
tzpos=tz_opn+" Today to " +tz_cls+ " Next day";
}
//--
return(tzpos);
//----
} //-end PosTimeZone()
//---------//
void MCEA::Set_Time_Zone(void)
{
//---
//-- Server Time==TimeCurrent()
datetime TTS=TimeTradeServer();
datetime GMT=TimeGMT();
//--
MqlDateTime svrtm,gmttm;
TimeToStruct(TTS,svrtm);
TimeToStruct(GMT,gmttm);
int svrhr=svrtm.hour; // Server time hour
int gmthr=gmttm.hour; // GMT time hour
int difhr=svrhr-gmthr; // Time difference Server time to GMT time
//--
int NZSGMT=12; // New Zealand Session GMT/UTC+12
int AUSGMT=10; // Australia Sydney Session GMT/UTC+10
int TOKGMT=9; // Asia Tokyo Session GMT/UTC+9
int EURGMT=0; // Europe London Session GMT/UTC 0
int USNGMT=-5; // US New York Session GMT/UTC-5
//--
int NZSStm=8; // New Zealand Session time start: 08:00 Local Time
int NZSCtm=17; // New Zealand Session time close: 17:00 Local Time
int AUSStm=7; // Australia Sydney Session time start: 07:00 Local Time
int AUSCtm=17; // Australia Sydney Session time close: 17:00 Local Time
int TOKStm=9; // Asia Tokyo Session time start: 09:00 Local Time
int TOKCtm=18; // Asia Tokyo Session time close: 18:00 Local Time
int EURStm=9; // Europe London Session time start: 09:00 Local Time
int EURCtm=19; // Europe London Session time close: 19:00 Local Time
int USNStm=8; // US New York Session time start: 08:00 Local Time
int USNCtm=17; // US New York Session time close: 17:00 Local Time
//--
int nzo = (NZSStm+difhr-NZSGMT)<0 ? 24+(NZSStm+difhr-NZSGMT) : (NZSStm+difhr-NZSGMT);
int nzc = (NZSCtm+difhr-NZSGMT)<0 ? 24+(NZSCtm+difhr-NZSGMT) : (NZSCtm+difhr-NZSGMT);
//--
int auo = (AUSStm+difhr-AUSGMT)<0 ? 24+(AUSStm+difhr-AUSGMT) : (AUSStm+difhr-AUSGMT);
int auc = (AUSCtm+difhr-AUSGMT)<0 ? 24+(AUSCtm+difhr-AUSGMT) : (AUSCtm+difhr-AUSGMT);
//--
int tko = (TOKStm+difhr-TOKGMT)<0 ? 24+(TOKStm+difhr-TOKGMT) : (TOKStm+difhr-TOKGMT);
int tkc = (TOKCtm+difhr-TOKGMT)<0 ? 24+(TOKCtm+difhr-TOKGMT) : (TOKCtm+difhr-TOKGMT);
//--
int euo = (EURStm+difhr-EURGMT)<0 ? 24+(EURStm+difhr-EURGMT) : (EURStm+difhr-EURGMT);
int euc = (EURCtm+difhr-EURGMT)<0 ? 24+(EURCtm+difhr-EURGMT) : (EURCtm+difhr-EURGMT);
//--
int uso = (USNStm+difhr-USNGMT)<0 ? 24+(USNStm+difhr-USNGMT) : (USNStm+difhr-USNGMT);
int usc = (USNCtm+difhr-USNGMT)<0 ? 24+(USNCtm+difhr-USNGMT) : (USNCtm+difhr-USNGMT);
if(usc==0||usc==24) usc=23;
//--
//---Trading on Custom Session
int _days00=ThisTime(day);
int _days10=ThisTime(day);
if(stsescuh>clsescuh) _days10=ThisTime(day)+1;
tmopcu=ReqDate(_days00,stsescuh,stsescum);
tmclcu=ReqDate(_days10,clsescuh,clsescum);
//--
//--Trading on New Zealand Session GMT/UTC+12
int _days01=ThisTime(hour)<nzc ? ThisTime(day)-1 : ThisTime(day);
int _days11=ThisTime(hour)<nzc ? ThisTime(day) : ThisTime(day)+1;
tmop01=ReqDate(_days01,nzo,0); // start: 08:00 Local Time == 20:00 GMT/UTC
tmcl01=ReqDate(_days11,nzc-1,59); // close: 17:00 Local Time == 05:00 GMT/UTC
//--
//--Trading on Australia Sydney Session GMT/UTC+10
int _days02=ThisTime(hour)<auc ? ThisTime(day)-1 : ThisTime(day);
int _days12=ThisTime(hour)<auc ? ThisTime(day) : ThisTime(day)+1;
tmop02=ReqDate(_days02,auo,0); // start: 07:00 Local Time == 21:00 GMT/UTC
tmcl02=ReqDate(_days12,auc-1,59); // close: 17:00 Local Time == 07:00 GMT/UTC
//--
//--Trading on Asia Tokyo Session GMT/UTC+9
int _days03=ThisTime(hour)<tkc ? ThisTime(day) : ThisTime(day)+1;
int _days13=ThisTime(hour)<tkc ? ThisTime(day) : ThisTime(day)+1;
tmop03=ReqDate(_days03,tko,0); // start: 09:00 Local Time == 00:00 GMT/UTC
tmcl03=ReqDate(_days13,tkc-1,59); // close: 18:00 Local Time == 09:00 GMT/UTC
//--
//--Trading on Europe London Session GMT/UTC 00:00
int _days04=ThisTime(hour)<euc ? ThisTime(day) : ThisTime(day)+1;
int _days14=ThisTime(hour)<euc ? ThisTime(day) : ThisTime(day)+1;
tmop04=ReqDate(_days04,euo,0); // start: 09:00 Local Time == 09:00 GMT/UTC
tmcl04=ReqDate(_days14,euc-1,59); // close: 19:00 Local Time == 19:00 GMT/UTC
//--
//--Trading on US New York Session GMT/UTC-5
int _days05=ThisTime(hour)<usc ? ThisTime(day) : ThisTime(day)+1;
int _days15=ThisTime(hour)<=usc ? ThisTime(day) : ThisTime(day)+1;
tmop05=ReqDate(_days05,uso,0); // start: 08:00 Local Time == 13:00 GMT/UTC
tmcl05=ReqDate(_days15,usc,59); // close: 17:00 Local Time == 22:00 GMT/UTC
//--
//--Not Use Trading Time Zone
if(trd_time_zone==No)
{
tmopno=ReqDate(ThisTime(day),0,15);
tmclno=ReqDate(ThisTime(day),23,59);
}
//--
Time_Zone();
//--
return;
//---
} //-end Set_Time_Zone()
//---------//
void MCEA::Time_Zone(void)
{
//---
//--
tz_ses="";
//--
switch(session)
{
case Cus_Session:
{
SesCuOp=StringToTime(tmopcu);
SesCuCl=StringToTime(tmclcu);
zntm=SesCuOp;
znop=SesCuOp;
zncl=SesCuCl;
tz_ses="Custom_Session";
tz_opn=timehr(stsescuh,stsescum);
tz_cls=timehr(clsescuh,clsescum);
break;
}
case New_Zealand:
{
Ses01Op=StringToTime(tmop01);
Ses01Cl=StringToTime(tmcl01);
zntm=Ses01Op;
znop=Ses01Op;
zncl=Ses01Cl;
tz_ses="New_Zealand/Oceania";
tz_opn=timehr(ReqTime(Ses01Op,hour),ReqTime(Ses01Op,min));
tz_cls=timehr(ReqTime(Ses01Cl,hour),ReqTime(Ses01Cl,min));
break;
}
case Australia:
{
Ses02Op=StringToTime(tmop02);
Ses02Cl=StringToTime(tmcl02);
zntm=Ses02Op;
znop=Ses02Op;
zncl=Ses02Cl;
tz_ses="Australia Sydney";
tz_opn=timehr(ReqTime(Ses02Op,hour),ReqTime(Ses02Op,min));
tz_cls=timehr(ReqTime(Ses02Cl,hour),ReqTime(Ses02Cl,min));
break;
}
case Asia_Tokyo:
{
Ses03Op=StringToTime(tmop03);
Ses03Cl=StringToTime(tmcl03);
zntm=Ses03Op;
znop=Ses03Op;
zncl=Ses03Cl;
tz_ses="Asia/Tokyo";
tz_opn=timehr(ReqTime(Ses03Op,hour),ReqTime(Ses03Op,min));
tz_cls=timehr(ReqTime(Ses03Cl,hour),ReqTime(Ses03Cl,min));
break;
}
case Europe_London:
{
Ses04Op=StringToTime(tmop04);
Ses04Cl=StringToTime(tmcl04);
zntm=Ses04Op;
znop=Ses04Op;
zncl=Ses04Cl;
tz_ses="Europe/London";
tz_opn=timehr(ReqTime(Ses04Op,hour),ReqTime(Ses04Op,min));
tz_cls=timehr(ReqTime(Ses04Cl,hour),ReqTime(Ses04Cl,min));
break;
}
case US_New_York:
{
Ses05Op=StringToTime(tmop05);
Ses05Cl=StringToTime(tmcl05);
zntm=Ses05Op;
znop=Ses05Op;
zncl=Ses05Cl;
tz_ses="US/New_York";
tz_opn=timehr(ReqTime(Ses05Op,hour),ReqTime(Ses05Op,min));
tz_cls=timehr(ReqTime(Ses05Cl,hour),ReqTime(Ses05Cl,min));
break;
}
}
//--
if(trd_time_zone==No)
{
SesNoOp=StringToTime(tmopno);
SesNoCl=StringToTime(tmclno);
zntm=SesNoOp;
znop=SesNoOp;
zncl=SesNoCl;
tz_ses="Not Use Time Zone";
tz_opn=timehr(ReqTime(SesNoOp,hour),ReqTime(SesNoOp,min));
tz_cls=timehr(ReqTime(SesNoCl,hour),ReqTime(SesNoCl,min));
}
//--
return;
//---
} //-end Time_Zone()
//---------//
bool MCEA::Trade_session(void)
{
//---
bool trd_ses=false;
ishour=ThisTime(hour);
if(ishour!=onhour) Set_Time_Zone();
datetime tcurr=TimeCurrent(); // Server Time
//--
switch(session)
{
case Cus_Session:
{
if(tcurr>=SesCuOp && tcurr<=SesCuCl) trd_ses=true;
break;
}
case New_Zealand:
{
if(tcurr>=Ses01Op && tcurr<=Ses01Cl) trd_ses=true;
break;
}
case Australia:
{
if(tcurr>=Ses02Op && tcurr<=Ses02Cl) trd_ses=true;
break;
}
case Asia_Tokyo:
{
if(tcurr>=Ses03Op && tcurr<=Ses03Cl) trd_ses=true;
break;
}
case Europe_London:
{
if(tcurr>=Ses04Op && tcurr<=Ses04Cl) trd_ses=true;
break;
}
case US_New_York:
{
if(tcurr>=Ses05Op && tcurr<=Ses05Cl) trd_ses=true;
break;
}
}
//--
if(trd_time_zone==No)
{
if(tcurr>=SesNoOp && tcurr<=SesNoCl) trd_ses=true;
}
//--
onhour=ishour;
//--
return(trd_ses);
//---
} //-end Trade_session()
//---------//
string MCEA::TradingDay(void)
{
//---
int trdday=ThisTime(dow);
switch(trdday)
{
case 0: daytrade="Sunday"; break;
case 1: daytrade="Monday"; break;
case 2: daytrade="Tuesday"; break;
case 3: daytrade="Wednesday"; break;
case 4: daytrade="Thursday"; break;
case 5: daytrade="Friday"; break;
case 6: daytrade="Saturday"; break;
}
return(daytrade);
//---
} //-end TradingDay()
//---------//
bool MCEA::TradingToday(void)
{
//---
bool tradetoday=false;
int trdday=ThisTime(dow);
hariini="No";
//--
int ttd[];
ArrayResize(ttd,7);
ttd[0]=ttd0;
ttd[1]=ttd1;
ttd[2]=ttd2;
ttd[3]=ttd3;
ttd[4]=ttd4;
ttd[5]=ttd5;
ttd[6]=ttd6;
//--
if(ttd[trdday]==Yes) {tradetoday=true; hariini="Yes";}
//--
return(tradetoday);
//---
} //-end TradingToday()
//---------//
string MCEA::timehr(int hr,int mn)
{
//---
string scon="";
string men=mn==0 ? "00" : string(mn);
int shr=hr==24 ? 0 : hr;
if(shr<10) scon="0"+string(shr)+":"+men;
else scon=string(shr)+":"+men;
//--
return(scon);
//---
} //-end timehr()
//---------//
string MCEA::ReqDate(int d,int h,int m)
{
//---
MqlDateTime mdt;
datetime t=TimeCurrent(mdt);
x_year=mdt.year;
x_mon=mdt.mon;
x_day=d;
x_hour=h;
x_min=m;
x_sec=mdt.sec;
//--
string mdr=string(x_year)+"."+string(x_mon)+"."+string(x_day)+" "+timehr(x_hour,x_min);
return(mdr);
//---
} //-end ReqDate()
//---------//
int MCEA::ThisTime(const int reqmode)
{
//---
MqlDateTime tm;
TimeCurrent(tm);
int valtm=0;
//--
switch(reqmode)
{
case 0: valtm=tm.year; break; // Return Year
case 1: valtm=tm.mon; break; // Return Month
case 2: valtm=tm.day; break; // Return Day
case 3: valtm=tm.hour; break; // Return Hour
case 4: valtm=tm.min; break; // Return Minutes
case 5: valtm=tm.sec; break; // Return Seconds
case 6: valtm=tm.day_of_week; break; // Return Day of week (0-Sunday, 1-Monday, ... ,6-Saturday)
case 7: valtm=tm.day_of_year; break; // Return Day number of the year (January 1st is assigned the number value of zero)
}
//--
return(valtm);
//---
} //-end ThisTime()
//---------//
int MCEA::ReqTime(datetime reqtime,
const int reqmode)
{
MqlDateTime tm;
TimeToStruct(reqtime,tm);
int valtm=0;
//--
switch(reqmode)
{
case 0: valtm=tm.year; break; // Return Year
case 1: valtm=tm.mon; break; // Return Month
case 2: valtm=tm.day; break; // Return Day
case 3: valtm=tm.hour; break; // Return Hour
case 4: valtm=tm.min; break; // Return Minutes
case 5: valtm=tm.sec; break; // Return Seconds
case 6: valtm=tm.day_of_week; break; // Return Day of week (0-Sunday, 1-Monday, ... ,6-Saturday)
case 7: valtm=tm.day_of_year; break; // Return Day number of the year (January 1st is assigned the number value of zero)
}
//--
return(valtm);
//---
} //-end ReqTime()
//---------//
string MCEA::AccountMode() // function: to known account trade mode
{
//----
//--- Demo, Contest or Real account
ENUM_ACCOUNT_TRADE_MODE account_type=(ENUM_ACCOUNT_TRADE_MODE)AccountInfoInteger(ACCOUNT_TRADE_MODE);
//---
trade_mode="";
//--
switch(account_type)
{
case ACCOUNT_TRADE_MODE_DEMO:
trade_mode="Demo";
break;
case ACCOUNT_TRADE_MODE_CONTEST:
trade_mode="Contest";
break;
default:
trade_mode="Real";
break;
}
//--
return(trade_mode);
//----
} //-end AccountMode()
//---------//
void MCEA::Do_Alerts(const string symbol,string msgText)
{
//---
//--
Print(expname+"--- "+symbol+": "+msgText+
"\n--- at: ",TimeToString(TimeCurrent(),TIME_DATE|TIME_MINUTES));
//--
if(alerts==Yes)
{
Alert(expname+"--- "+symbol+": "+msgText+
"--- at: ",TimeToString(TimeCurrent(),TIME_DATE|TIME_MINUTES));
}
//--
if(UseEmailAlert==Yes)
SendMail(expname,"--- "+symbol+" "+TF2Str(PERIOD_CURRENT)+": "+msgText+
"\n--- at: "+TimeToString(TimeCurrent(),TIME_DATE|TIME_MINUTES));
//--
if(UseSendnotify==Yes)
SendNotification(expname+"--- "+symbol+" "+TF2Str(PERIOD_CURRENT)+": "+msgText+
"\n--- at: "+TimeToString(iTime(symbol,0,0),TIME_DATE|TIME_MINUTES));
//--
return;
//--
//---
} //-end Do_Alerts()
//---------//
string MCEA::TF2Str(ENUM_TIMEFRAMES period)
{
//---
switch(period)
{
//--
case PERIOD_M1: return("M1");
case PERIOD_M2: return("M2");
case PERIOD_M3: return("M3");
case PERIOD_M4: return("M4");
case PERIOD_M5: return("M5");
case PERIOD_M6: return("M6");
case PERIOD_M10: return("M10");
case PERIOD_M12: return("M12");
case PERIOD_M15: return("M15");
case PERIOD_M20: return("M20");
case PERIOD_M30: return("M30");
case PERIOD_H1: return("H1");
case PERIOD_H2: return("H2");
case PERIOD_H3: return("H3");
case PERIOD_H4: return("H4");
case PERIOD_H6: return("H6");
case PERIOD_H8: return("H8");
case PERIOD_H12: return("H12");
case PERIOD_D1: return("D1");
case PERIOD_W1: return("W1");
case PERIOD_MN1: return("MN1");
//--
}
return(string(period));
//---
} //-end TF2Str()
//---------//
string MCEA::getUninitReasonText(int reasonCode)
{
//---
string text="";
//---
switch(reasonCode)
{
case REASON_PROGRAM:
text="The EA has stopped working calling by remove function."; break;
case REASON_REMOVE:
text="Program "+__FILE__+" was removed from chart"; break;
case REASON_RECOMPILE:
text="Program recompiled."; break;
case REASON_CHARTCHANGE:
text="Symbol or timeframe was changed"; break;
case REASON_CHARTCLOSE:
text="Chart was closed"; break;
case REASON_PARAMETERS:
text="Input-parameter was changed"; break;
case REASON_ACCOUNT:
text="Account was changed"; break;
case REASON_TEMPLATE:
text="New template was applied to chart"; break;
case REASON_INITFAILED:
text="The OnInit() handler returned a non-zero value."; break;
case REASON_CLOSE:
text="Terminal closed."; break;
default: text="Another reason"; break;
}
//--
return text;
//---
} //-end getUninitReasonText()
//---------//
//+------------------------------------------------------------------+
//| ChartEvent function |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
const long &lparam,
const double &dparam,
const string &sparam)
{
//---
//--- handling CHARTEVENT_CLICK event ("Clicking the chart")
ResetLastError();
//--
ENUM_TIMEFRAMES CCS=mc.TFt;
//--
if(id==CHARTEVENT_OBJECT_CLICK)
{
int lensymbol=StringLen(Symbol());
int lensparam=StringLen(sparam);
//--
//--- if "Set SL All Orders" button is click
if(sparam=="Set SL/TP All Orders")
{
mc.SetSLTPOrders();
Alert("-- "+mc.expname+" -- ",Symbol()," -- Set SL/TP All Orders");
//--- unpress the button
ObjectSetInteger(0,"Set SL/TP All Orders",OBJPROP_STATE,false);
ObjectSetInteger(0,"Set SL/TP All Orders",OBJPROP_ZORDER,0);
CreateManualPanel();
}
//--- if "Close All Order" button is click
if(sparam=="Close All Order")
{
mc.CloseAllOrders();
Alert("-- "+mc.expname+" -- ",Symbol()," -- Close All Orders");
//--- unpress the button
ObjectSetInteger(0,"Close All Order",OBJPROP_STATE,false);
ObjectSetInteger(0,"Close All Order",OBJPROP_ZORDER,0);
CreateManualPanel();
}
//--- if "Close All Profit" button is click
if(sparam=="Close All Profit")
{
mc.ManualCloseAllProfit();
Alert("-- "+mc.expname+" -- ",Symbol()," -- Close All Profit");
//--- unpress the button
ObjectSetInteger(0,"Close All Profit",OBJPROP_STATE,false);
ObjectSetInteger(0,"Close All Profit",OBJPROP_ZORDER,0);
CreateManualPanel();
}
//--- if "X" button is click
if(sparam=="X")
{
ObjectsDeleteAll(0,0,OBJ_BUTTON);
ObjectsDeleteAll(0,0,OBJ_LABEL);
ObjectsDeleteAll(0,0,OBJ_RECTANGLE_LABEL);
//--- unpress the button
ObjectSetInteger(0,"X",OBJPROP_STATE,false);
ObjectSetInteger(0,"X",OBJPROP_ZORDER,0);
//--
DeleteButtonX();
mc.PanelExtra=false;
DisplayManualButton();
}
//--- if "M" button is click
if(sparam=="M")
{
//--- unpress the button
ObjectSetInteger(0,"M",OBJPROP_STATE,false);
ObjectSetInteger(0,"M",OBJPROP_ZORDER,0);
mc.PanelExtra=true;
CreateManualPanel();
}
//--- if "C" button is click
if(sparam=="C")
{
//--- unpress the button
ObjectSetInteger(0,"C",OBJPROP_STATE,false);
ObjectSetInteger(0,"C",OBJPROP_ZORDER,0);
mc.PanelExtra=true;
CreateSymbolPanel();
}
//--- if "R" button is click
if(sparam=="R")
{
Alert("-- "+mc.expname+" -- ",Symbol()," -- expert advisor will be Remove from the chart.");
ExpertRemove();
//--- unpress the button
ObjectSetInteger(0,"R",OBJPROP_STATE,false);
ObjectSetInteger(0,"R",OBJPROP_ZORDER,0);
if(!ChartSetSymbolPeriod(0,Symbol(),Period()))
ChartSetSymbolPeriod(0,Symbol(),Period());
DeletePanelButton();
ChartRedraw(0);
}
//--- if Symbol button is click
if(lensparam==lensymbol)
{
int sx=mc.ValidatePairs(sparam);
ChangeChartSymbol(mc.AS30[sx],CCS);
mc.PanelExtra=false;
}
//--
}
//--
return;
//---
} //-end OnChartEvent()
//---------//
void ChangeChartSymbol(string c_symbol,ENUM_TIMEFRAMES cstf)
{
//---
//--- unpress the button
ObjectSetInteger(0,c_symbol,OBJPROP_STATE,false);
ObjectSetInteger(0,c_symbol,OBJPROP_ZORDER,0);
ObjectsDeleteAll(0,0,OBJ_BUTTON);
ObjectsDeleteAll(0,0,OBJ_LABEL);
ObjectsDeleteAll(0,0,OBJ_RECTANGLE_LABEL);
//--
ChartSetSymbolPeriod(0,c_symbol,cstf);
//--
ChartRedraw(0);
//--
return;
//---
} //-end ChangeChartSymbol()
//---------//
int WS(int width) // Width Scaling factor wide button
{
//---
int res=0;
int reswidth=0;
//--- Calculating the scaling factor wide button on a screen
int scale_factor=(TerminalInfoInteger(TERMINAL_SCREEN_DPI));
//--- Use of the scaling factor
reswidth=(width * scale_factor) / 96;
double res1=NormalizeDouble(reswidth*1.25,0);
res=int(res1);
//--
return(res);
//---
} //-end WS()
//---------//
void CreateManualPanel()
{
//---
//--
CreateButtonTemplate(0,"TemplateSL",160,35,STYLE_SOLID,5,BORDER_RAISED,clrNONE,clrBurlyWood,clrWhite,CORNER_RIGHT_UPPER,170,45,true);
CreateButtonTemplate(0,"TempStatSL",154,30,STYLE_SOLID,3,BORDER_RAISED,clrNONE,clrGreen,clrWhite,CORNER_RIGHT_UPPER,167,48,true);
CreateButtonClick(0,"Set SL/TP All Orders",143,21,"Bodoni MT Black",10,BORDER_RAISED,"Set SL/TP All Orders",clrNONE,clrRed,clrWhite,ANCHOR_CENTER,CORNER_RIGHT_UPPER,162,56,true,"Set SL/TP All Orders");
//--
CreateButtonTemplate(0,"TemplateS",160,35,STYLE_SOLID,5,BORDER_RAISED,clrNONE,clrBurlyWood,clrWhite,CORNER_RIGHT_UPPER,170,77,true);
CreateButtonTemplate(0,"TempStats",154,30,STYLE_SOLID,3,BORDER_RAISED,clrNONE,clrGreen,clrWhite,CORNER_RIGHT_UPPER,167,79,true);
CreateButtonClick(0,"Close All Order",143,21,"Bodoni MT Black",10,BORDER_RAISED,"Close All Order",clrNONE,clrRed,clrWhite,ANCHOR_CENTER,CORNER_RIGHT_UPPER,162,88,true,"Close All Order");
//--
CreateButtonTemplate(0,"TemplateC",160,35,STYLE_SOLID,5,BORDER_RAISED,clrNONE,clrBurlyWood,clrWhite,CORNER_RIGHT_UPPER,170,109,true);
CreateButtonTemplate(0,"TempStatC",154,30,STYLE_SOLID,3,BORDER_RAISED,clrNONE,clrGreen,clrWhite,CORNER_RIGHT_UPPER,167,111,true);
CreateButtonClick(0,"Close All Profit",143,21,"Bodoni MT Black",10,BORDER_RAISED,"Close All Profit",clrNONE,clrRed,clrWhite,ANCHOR_CENTER,CORNER_RIGHT_UPPER,162,120,true,"Close All Profit");
//--
DeletePanelButton();
CreateButtonClick(0,"X",17,15,"Arial Black",12,BORDER_RAISED,"X",clrNONE,clrWhite,clrRed,ANCHOR_CENTER,CORNER_RIGHT_UPPER,27,31,true,"Close panel");
//--
ChartRedraw(0);
//--
return;
//---
} //-end CreateManualPanel()
//---------//
void DisplayManualButton(void)
{
//--
DeleteButtonX();
CreateButtonClick(0,"M",17,16,"Arial Black",11,BORDER_FLAT,"M",clrWhite,clrWhite,clrRed,ANCHOR_CENTER,CORNER_RIGHT_UPPER,61,21,true,"Open Manual Panel");
CreateButtonClick(0,"C",17,16,"Arial Black",11,BORDER_FLAT,"C",clrWhite,clrWhite,clrRed,ANCHOR_CENTER,CORNER_RIGHT_UPPER,41,21,true,"Change Chart Symbol");
CreateButtonClick(0,"R",17,16,"Arial Black",11,BORDER_FLAT,"R",clrWhite,clrWhite,clrRed,ANCHOR_CENTER,CORNER_RIGHT_UPPER,21,21,true,"Expert Remove");
ChartRedraw(0);
//--
return;
//--
} //-end DisplayManualButton()
//---------//
bool DisplayManualButton(string a,string b,string c)
{
//--
if(ObjectFind(0,a)<0 && ObjectFind(0,b)<0 && ObjectFind(0,c)<0 && !mc.PanelExtra)
return(false);
return(true);
//--
} //-end DisplayManualButton()
//---------//
void DeleteButtonX(void)
{
//--
ObjectDelete(0,"X");
//--
ChartRedraw(0);
//--
return;
//--
} //-end DeleteButtonX()
//---------//
void DeletePanelButton(void)
{
//--
ObjectDelete(0,"M");
ObjectDelete(0,"C");
ObjectDelete(0,"R");
//--
return;
//--
} //-end DeletePanelButton()
//---------//
void CreateSymbolPanel()
{
//---
//--
ResetLastError();
DeletePanelButton();
int sydis=83;
int tsatu=int(mc.sall/2);
//--
CreateButtonTemplate(0,"Template",180,367,STYLE_SOLID,5,BORDER_RAISED,clrYellow,clrBurlyWood,clrWhite,CORNER_RIGHT_UPPER,187,45,true);
CreateButtonTemplate(0,"TempCCS",167,25,STYLE_SOLID,5,BORDER_RAISED,clrYellow,clrBlue,clrWhite,CORNER_RIGHT_UPPER,181,50,true);
CreateButtonClick(0,"X",14,14,"Arial Black",10,BORDER_FLAT,"X",clrWhite,clrWhite,clrRed,ANCHOR_CENTER,CORNER_RIGHT_UPPER,22,48,true,"Close Symbol Panel");
//--
string chsym="Change SYMBOL";
int cspos=int(181/2)+int(StringLen(chsym)/2);
CreateButtontLable(0,"CCS","Bodoni MT Black",chsym,11,clrWhite,ANCHOR_CENTER,CORNER_RIGHT_UPPER,cspos,62,true,"Change Chart Symbol");
//--
for(int i=0; i<tsatu; i++)
CreateButtonClick(0,mc.AS30[i],80,17,"Bodoni MT Black",8,BORDER_RAISED,mc.AS30[i],clrYellow,clrBlue,clrWhite,ANCHOR_CENTER,CORNER_RIGHT_UPPER,180,sydis+(i*22),true,"Change to "+mc.AS30[i]);
//--
for(int i=tsatu; i<mc.sall; i++)
CreateButtonClick(0,mc.AS30[i],80,17,"Bodoni MT Black",8,BORDER_RAISED,mc.AS30[i],clrYellow,clrBlue,clrWhite,ANCHOR_CENTER,CORNER_RIGHT_UPPER,94,sydis+((i-tsatu)*22),true,"Change to "+mc.AS30[i]);
//--
ChartRedraw(0);
//--
return;
//---
} //-end CreateSymbolPanel()
//---------//
void CreateButtonClick(long chartid,
string button_name,
int button_x_size,
int button_y_size,
string button_font_model,
int button_font_size,
int button_border,
string button_name_text,
color button_bord_color,
color button_bg_color,
color button_color,
int button_anchor,
int button_corner,
int button_xdist,
int button_ydist,
bool button_hidden,
string tooltip)
{
//---
ObjectCreate(chartid,button_name,OBJ_BUTTON,0,0,0); // create button
ObjectSetInteger(chartid,button_name,OBJPROP_XSIZE,WS(button_x_size));
ObjectSetInteger(chartid,button_name,OBJPROP_YSIZE,button_y_size);
ObjectSetString(chartid,button_name,OBJPROP_TEXT,button_name_text);
ObjectSetString(chartid,button_name,OBJPROP_FONT,button_font_model);
ObjectSetInteger(chartid,button_name,OBJPROP_FONTSIZE,button_font_size);
ObjectSetInteger(chartid,button_name,OBJPROP_BORDER_TYPE,button_border);
ObjectSetInteger(chartid,button_name,OBJPROP_BORDER_COLOR,button_bord_color);
ObjectSetInteger(chartid,button_name,OBJPROP_BGCOLOR,button_bg_color);
ObjectSetInteger(chartid,button_name,OBJPROP_COLOR,button_color);
ObjectSetInteger(chartid,button_name,OBJPROP_ANCHOR,button_anchor);
ObjectSetInteger(chartid,button_name,OBJPROP_CORNER,button_corner);
ObjectSetInteger(chartid,button_name,OBJPROP_XDISTANCE,WS(button_xdist));
ObjectSetInteger(chartid,button_name,OBJPROP_YDISTANCE,button_ydist);
ObjectSetInteger(chartid,button_name,OBJPROP_HIDDEN,button_hidden);
ObjectSetString(chartid,button_name,OBJPROP_TOOLTIP,tooltip);
ChartRedraw(0);
//--
return;
//---
} //-end CreateButtonClick()
//---------//
void CreateButtonTemplate(long chartid,
string obj_name,
int x_size,
int y_size,
int style,
int width,
int border,
color bordcolor,
color bgcolor,
color objcolor,
int corner,
int x_dist,
int y_dist,
bool hidden)
{
//---
ObjectCreate(chartid,obj_name,OBJ_RECTANGLE_LABEL,0,0,0); // create Rectangle Label
ObjectSetInteger(chartid,obj_name,OBJPROP_XSIZE,WS(x_size));
ObjectSetInteger(chartid,obj_name,OBJPROP_YSIZE,y_size);
ObjectSetInteger(chartid,obj_name,OBJPROP_STYLE,style);
ObjectSetInteger(chartid,obj_name,OBJPROP_WIDTH,width);
ObjectSetInteger(chartid,obj_name,OBJPROP_BORDER_TYPE,border);
ObjectSetInteger(chartid,obj_name,OBJPROP_BORDER_COLOR,bordcolor);
ObjectSetInteger(chartid,obj_name,OBJPROP_BGCOLOR,bgcolor);
ObjectSetInteger(chartid,obj_name,OBJPROP_COLOR,objcolor);
ObjectSetInteger(chartid,obj_name,OBJPROP_CORNER,corner);
ObjectSetInteger(chartid,obj_name,OBJPROP_XDISTANCE,WS(x_dist));
ObjectSetInteger(chartid,obj_name,OBJPROP_YDISTANCE,y_dist);
ObjectSetInteger(chartid,obj_name,OBJPROP_HIDDEN,hidden);
ChartRedraw(0);
//--
return;
//---
} //-end CreateButtonTemplate()
//---------//
void CreateButtontLable(long chartid,
string lable_name,
string lable_font_model,
string lable_obj_text,
int lable_font_size,
color lable_color,
int lable_anchor,
int lable_corner,
int lable_xdist,
int lable_ydist,
bool lable_hidden,
string tooltip)
{
//---
ObjectDelete(chartid,lable_name);
ObjectCreate(chartid,lable_name,OBJ_LABEL,0,0,0,0,0); // create Lable
ObjectSetInteger(chartid,lable_name,OBJPROP_FONTSIZE,lable_font_size);
ObjectSetString(chartid,lable_name,OBJPROP_FONT,lable_font_model);
ObjectSetString(chartid,lable_name,OBJPROP_TEXT,lable_obj_text);
ObjectSetInteger(chartid,lable_name,OBJPROP_COLOR,lable_color);
ObjectSetInteger(chartid,lable_name,OBJPROP_ANCHOR,lable_anchor);
ObjectSetInteger(chartid,lable_name,OBJPROP_CORNER,lable_corner);
ObjectSetInteger(chartid,lable_name,OBJPROP_XDISTANCE,WS(lable_xdist));
ObjectSetInteger(chartid,lable_name,OBJPROP_YDISTANCE,lable_ydist);
ObjectSetInteger(chartid,lable_name,OBJPROP_HIDDEN,lable_hidden);
ObjectSetString(chartid,lable_name,OBJPROP_TOOLTIP,tooltip);
ChartRedraw(0);
//--
return;
//---
} //-end CreateButtontLable()
//---------//
//--------------------------------------------------------------------//
***Copyright © 2026 3rjfx ~ For educational purposes only.***
Please download the Exp_MAxTenkanKijun Expert Advisor: Exp_MAxTenkanKijun
If you want to get the source code of the program, please send your request via the Contact page by mentioning the article and program you want.


No comments :
Post a Comment
Leave A Comment...