1444 lines
37 KiB
Plaintext
1444 lines
37 KiB
Plaintext
///////////////////////////////////////////////////////
|
|
//
|
|
// SaherElm IT Center XST Strategy Expert Advisor
|
|
// ---------------------------------------------
|
|
// saherelm implementation of strategy expert advisor ...
|
|
// in this EA, we try to combine multiple tools, to ashive best
|
|
// results ...
|
|
//
|
|
// ShortName: XST
|
|
//
|
|
// Maintainer:
|
|
// ------------
|
|
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
|
|
// +989121694056
|
|
//
|
|
//////////////////////////////////////////////////////
|
|
//
|
|
// Global Properties ...
|
|
#property copyright "Copyright 2023, SaherElm IT Center"
|
|
#property link "https://saherelm.ir"
|
|
#property version "1.00"
|
|
#property description "SaherElm XST Strategy Expert Advisor"
|
|
#property strict
|
|
|
|
//
|
|
// START Inputs ...
|
|
//
|
|
//
|
|
// Signal Prefixe ...
|
|
input string signalPrefix = "XST"; // Signal Prefix
|
|
|
|
//
|
|
// Signal Draw Specifications ...
|
|
input string bullishSignalLabel = "X_BUY"; // Bullish Signal Label
|
|
input color bullishSignalColor = clrAqua; // Bullish Signal Color
|
|
|
|
//
|
|
input string bearishSignalLabel = "X_SELL"; // Bearish Signal Label
|
|
input color bearishSignalColor = clrFuchsia; // Bearish Signal Color
|
|
|
|
//
|
|
input bool useOSCSignalling = false; // Use XOSC Signalling
|
|
input string oscSignalIdentifier = "XOSC"; // XOSC Signal Identifier
|
|
|
|
//
|
|
input bool useXMASignalling = false; // Use XMA Signalling
|
|
input string xmaSignalIdentifier = "XMA"; // XMA Signal Identifier
|
|
|
|
//
|
|
input bool useXSHPSignalling = true; // Use XSHP Signalling
|
|
input string xshpSignalIdentifier = "XSHP"; // XSHP Signal Identifier
|
|
|
|
//
|
|
input bool useXMNTMSignalling = false; // Use XMNTM Signalling
|
|
input string xmntmSignalIdentifier = "XMNTM"; // XMNTM Signal Identifier
|
|
|
|
//
|
|
input bool useXRSISignalling = true; // Use XRSI Signalling
|
|
input string xrsiSignalIdentifier = "XRSI"; // XRSI Signal Identifier
|
|
|
|
//
|
|
input color signalEntryColor = clrAquamarine; // Signal Entry Ptice Color
|
|
input color signalSLColor = clrRed; // Signal SL Color
|
|
input color signalTPColor = clrGreen; // Signal TP Color
|
|
|
|
//
|
|
// Trade ...
|
|
input bool allowTrade = true; // Allow Trade Based on given Signals
|
|
input bool allowLongTrades = true; // Allow Long Trades
|
|
input bool allowShortTrades = false; // Allow Short Trades
|
|
|
|
//
|
|
// Market Specification Inpouts ...
|
|
input int marketLength = 7; // Market Length
|
|
input double riskToRewardRatio = 2; // Risk to Reward Ratio
|
|
|
|
//
|
|
// Alerts ...
|
|
input bool alertEvents = true; // Alert Events
|
|
input bool alertPositions = true; // Alert Positions
|
|
input bool longPositionAlerts = true; // Alert Long Positions
|
|
input bool shortPositionAlerts = true; // Alert Short Positions
|
|
|
|
//
|
|
// Alert Types ...
|
|
input bool terminalAlert = false; // Terminal Alert
|
|
input bool pushAlert = false; // Push Notification Alerts
|
|
|
|
//
|
|
// Balance and Finanical Specifications ...
|
|
input double lotsPerTradePercent = 0.00001; // Lots Per Trade Percent
|
|
input int maxOpenTrades = 4; // Maximum Open Trade
|
|
input double maxDrawdownPercentPerPTrade = 0.015; // Maximum DrawDown Per Trade
|
|
input double minBalancePercent = 0.5; // Minimum Balance for Trading
|
|
input double maxEquityPercent = 0.1; // Maximum Trade Equity
|
|
input int closeAllOpenTradesAfterCandle = 504; // Close All Open Trades After Passed Candles
|
|
input bool closeAllInProfitOpenTradesWhenMaxOpenTradesReached = false; // Close All In Profit Open Trades When Max Open Trades Reached and New Signal Income
|
|
|
|
//
|
|
// OSC Inputs ...
|
|
//
|
|
// FastOSC ...
|
|
// Short Cycle (Fast OSC) ...
|
|
input int fastOSCLength = 10; // FastOSC Length
|
|
input double fastOSCMultiplier = 1.0; // FastOSC Multiplier
|
|
|
|
//
|
|
// SlowOSC ...
|
|
// Medium Cycle (Slow OSC) ...
|
|
input int slowOSCLength = 30; // SlowOSC Length
|
|
input double slowOSCMultiplier = 3.0; // SlowOSC Multiplier
|
|
|
|
//
|
|
// Power OSC ...
|
|
input double minPowerOSC = 0.04; // Minimum Signal Power
|
|
|
|
//
|
|
// Variance OSC ...
|
|
input double minVarianceOSC = 0.1; // Minimum Var Power
|
|
|
|
//
|
|
// ZIGZAG Inputs ...
|
|
input int zDeviation = 5; // ZigZag Deviation
|
|
input int zBackStep = 3; // ZigZag Back Step
|
|
|
|
//
|
|
// XMA Inputs ...
|
|
//
|
|
input double step = 0.02; // SAR Step
|
|
input double maximum = 0.2; // SAR Maximum
|
|
input int shortCycleFastMultiplier = 2; // Short Cycle Fast Multiplier
|
|
input int shortCycleSlowMultiplier = 4; // Short Cycle Slow Multiplier
|
|
input int mediumCycleFastMultiplier = 6; // Medium Cycle Fast Multiplier
|
|
input int mediumCycleSlowMultiplier = 12; // Medium Cycle Slow Multiplier
|
|
input int longCycleFastMultiplier = 36; // Long Cycle Fast Multiplier
|
|
input int longCycleSlowMultiplier = 72; // Long Cycle Slow Multiplier
|
|
//
|
|
// Show/Hide Inputs ...
|
|
input bool showPSar = false; // Show Parabolic Sar
|
|
input bool showMarketMiddle = false; // Show Market Middle
|
|
input bool showShortCycle = false; // Show Short Cycle
|
|
input bool showShortCycleCrossLines = false; // Show Short Cycle Vertical Lines
|
|
input bool showMediumCycle = false; // Show Medium Cycle
|
|
input bool showMediumCycleCrossLines = false; // Show Medium Cycle Vertical Lines
|
|
input bool showLongCycle = false; // Show Long Cycle
|
|
input bool showLongCycleCrossLines = false; // Show Long Cycle Vertical Lines
|
|
//
|
|
// Color Inputs ...
|
|
input color pSarColor = clrCornflowerBlue; // Parabolic Sar Color
|
|
input color shortCycleFastColor = clrGreen; // Short Cycle Fast Color ...
|
|
input color shortCycleSlowColor = clrRed; // Short Cycle Slow Color ...
|
|
input color mediumCycleFastColor = clrAqua; // Medium Cycle Fast Color ...
|
|
input color mediumCycleSlowColor = clrFuchsia; // Medium Cycle Slow Color ...
|
|
input color longCycleFastColor = clrGoldenrod; // Medium Cycle Fast Color ...
|
|
input color longCycleSlowColor = clrBrown; // Medium Cycle Slow Color ...
|
|
|
|
//
|
|
// XMKT Inputs ...
|
|
//
|
|
// Market Specifications ...
|
|
input bool showHighestHigh = false; // Show Market Highest High
|
|
input bool showHighestLow = false; // Show Market Highest Low
|
|
input bool showHighestOpen = false; // Show Market Highest Open
|
|
input bool showHighestClose = false; // Show Market Highest Close
|
|
input bool showLowestHigh = false; // Show Market Lowest High
|
|
input bool showLowestLow = false; // Show Market Lowest Low
|
|
input bool showLowestOpen = false; // Show Market Lowest Open
|
|
input bool showLowestClose = false; // Show Market Lowest Close
|
|
//
|
|
input color highestHighColor = clrDeepPink; // Market Highest High Color
|
|
input color highestLowColor = clrDarkOrange; // Market Highest Low Color
|
|
input color highestOpenColor = clrDodgerBlue; // Market Highest Open Color
|
|
input color highestCloseColor = clrOrchid; // Market Highest Close Color
|
|
input color lowestHighColor = clrHotPink; // Market Lowest High Color
|
|
input color lowestLowColor = clrOrange; // Market Lowest Low Color
|
|
input color lowestOpenColor = clrPowderBlue; // Market Lowest Open Color
|
|
input color lowestCloseColor = clrMediumOrchid; // Market Lowest Close Color
|
|
//
|
|
input ENUM_LINE_STYLE highestHighStyle = STYLE_DOT; // Market Highest High Line Style
|
|
input ENUM_LINE_STYLE highestLowStyle = STYLE_DOT; // Market Highest Low Line Style
|
|
input ENUM_LINE_STYLE highestOpenStyle = STYLE_DOT; // Market Highest Open Line Style
|
|
input ENUM_LINE_STYLE highestCloseStyle = STYLE_DOT; // Market Highest Close Line Style
|
|
input ENUM_LINE_STYLE lowestHighStyle = STYLE_DOT; // Market Lowest High Line Style
|
|
input ENUM_LINE_STYLE lowestLowStyle = STYLE_DOT; // Market Lowest Low Line Style
|
|
input ENUM_LINE_STYLE lowestOpenStyle = STYLE_DOT; // Market Lowest Open Line Style
|
|
input ENUM_LINE_STYLE lowestCloseStyle = STYLE_DOT; // Market Lowest Close Line Style
|
|
|
|
//
|
|
// SHPD Indicator ...
|
|
input double sharpDetectMultiplier = 500; // Sharp Detect Multiplier
|
|
|
|
// //
|
|
// input bool drawSharpDetectedLabels = false; // Draw Labels on Founded Sharps
|
|
|
|
// //
|
|
// input string sharpBullishLabel = "SH_BULL"; // Sharp Bullish Label
|
|
// input color sharpBullishColor = clrAqua; // Sharp Bullish color
|
|
|
|
// //
|
|
// input string sharpBearishLabel = "SH_BEAR"; // Sharp Bearish Label
|
|
// input color sharpBearishColor = clrFuchsia; // Sharp Bearish color
|
|
// //
|
|
//
|
|
// END Inputs ...
|
|
//
|
|
|
|
//
|
|
// START Global Definitions: Variables, Properties and etc ...
|
|
//
|
|
int lastSignalledBar = 0;
|
|
|
|
//
|
|
bool waitForLongSignals = true;
|
|
bool closeLongTrades = false;
|
|
|
|
//
|
|
bool waitForShortSignals = true;
|
|
bool closeShortTrades = false;
|
|
|
|
//
|
|
bool isMCGoingToClose;
|
|
bool isSharpBullishHappens;
|
|
bool isSharpBearishHappens;
|
|
|
|
//
|
|
datetime startMarketTime;
|
|
|
|
//
|
|
// Includes our shared library ...
|
|
#include "../Libraries/x-saherelm.lib.mq4"
|
|
|
|
//
|
|
// Includes our shared library ...
|
|
#include "../Libraries/x-saherelm.signal.lib.mq4"
|
|
//
|
|
// END Global Definitions: Variables, Properties and etc ...
|
|
//
|
|
|
|
//
|
|
// Start Event Handlers ...
|
|
//
|
|
//
|
|
// Initialization ...
|
|
int OnInit() {
|
|
//
|
|
// Validate Inputs ...
|
|
bool inputsNotValiid =
|
|
//
|
|
// MARKET ...
|
|
marketLength < 0
|
|
|| riskToRewardRatio < 0
|
|
//
|
|
// EA ...
|
|
|| lotsPerTradePercent < 0
|
|
|| maxOpenTrades <= 0
|
|
|| maxDrawdownPercentPerPTrade < 0
|
|
|| minBalancePercent < 0
|
|
|| maxEquityPercent < 0
|
|
|| marketLength < 0
|
|
//
|
|
// OSC ...
|
|
|| fastOSCLength < 0
|
|
|| fastOSCMultiplier < 0
|
|
|| slowOSCLength < 0
|
|
|| slowOSCMultiplier < 0
|
|
|| minPowerOSC < 0
|
|
|| minVarianceOSC < 0
|
|
|| slowOSCLength <= fastOSCLength
|
|
//
|
|
// ZIGZAG ...
|
|
|| zDeviation < 0
|
|
|| zBackStep < 0
|
|
|| zBackStep >= marketLength
|
|
//
|
|
// XMA ...
|
|
//
|
|
// Validate Short Cycle ...
|
|
|| shortCycleFastMultiplier <= 0
|
|
|| shortCycleSlowMultiplier <= 0
|
|
|| shortCycleFastMultiplier >= shortCycleSlowMultiplier
|
|
//
|
|
// Validate Medium Cycle ...
|
|
|| mediumCycleFastMultiplier <= 0
|
|
|| mediumCycleSlowMultiplier <= 0
|
|
|| mediumCycleFastMultiplier >= mediumCycleSlowMultiplier
|
|
//
|
|
// Validate Long Cycle ...
|
|
|| longCycleFastMultiplier <= 0
|
|
|| longCycleSlowMultiplier <= 0
|
|
|| longCycleFastMultiplier >= longCycleSlowMultiplier
|
|
//
|
|
// Validate Series of Multipliers ...
|
|
|| shortCycleFastMultiplier >= mediumCycleFastMultiplier
|
|
|| mediumCycleFastMultiplier >= longCycleFastMultiplier
|
|
;
|
|
|
|
if (inputsNotValiid) {
|
|
return INIT_PARAMETERS_INCORRECT;
|
|
}
|
|
|
|
//
|
|
totalSignals = 0;
|
|
totalLongSignals = 0;
|
|
totalShortSignals = 0;
|
|
|
|
//
|
|
initialBalance = 0;
|
|
|
|
//
|
|
// START Define Array Series ...
|
|
//
|
|
//
|
|
// END Define Array Series ...
|
|
//
|
|
|
|
//
|
|
// here we specify logging enabled or not ...
|
|
enableLogging = true;
|
|
|
|
//
|
|
// this is a Tag which attached to our Logger ...
|
|
logTag = "XST";
|
|
|
|
// //
|
|
// // Set Event Timer on One Seccond ...
|
|
// bool isEventSet = EventSetTimer(1);
|
|
// if (!isEventSet) {
|
|
// LogMessage("Error: " + GetLastError());
|
|
// return INIT_FAILED;
|
|
// }
|
|
|
|
//
|
|
return INIT_SUCCEEDED;
|
|
}
|
|
|
|
//
|
|
// DeInitialization ...
|
|
void OnDeinit(const int reason) {
|
|
//
|
|
// Killing Event Timer ...
|
|
EventKillTimer();
|
|
}
|
|
|
|
//
|
|
// Ticker Event Handler ...
|
|
void OnTick() {
|
|
//
|
|
isNewDay = IsNewDay();
|
|
if (isNewDay) {
|
|
//
|
|
LogMessage(
|
|
StringConcatenate(
|
|
"New Day: ", TimeCurrent()
|
|
)
|
|
);
|
|
}
|
|
|
|
//
|
|
// Process Signals to Open Positions ...
|
|
ProcessSignals();
|
|
|
|
//
|
|
// Checking State for Signal Handling ...
|
|
CheckState();
|
|
|
|
//
|
|
// Process Open Positions for Trailing Stop Loss or Close ...
|
|
ProcessOpenPositions();
|
|
}
|
|
|
|
//
|
|
// Timer Event Handler ...
|
|
void OnTimer() {
|
|
//
|
|
CheckState();
|
|
|
|
//
|
|
ProcessOpenPositions();
|
|
}
|
|
//
|
|
// END Event Handlers ...
|
|
//
|
|
|
|
//
|
|
// START Functions ...
|
|
//
|
|
//
|
|
// START Signal Related Functions ...
|
|
//
|
|
//
|
|
// Calculate Signal ...
|
|
// in this function we calculate a signal exists in
|
|
// specific bar or not ...
|
|
XSignalRequest GenerateSignal(
|
|
const int bar_index // Bar Index ...
|
|
) {
|
|
//
|
|
// create temp result ...
|
|
XSignalRequest result = {};
|
|
result.hasSignal = false;
|
|
result.type = X_NONE;
|
|
|
|
//
|
|
XSignal signal = {};
|
|
|
|
//
|
|
XOSCState emptyOscState = {};
|
|
ArrayFree(oscStates);
|
|
ArrayResize(
|
|
oscStates,
|
|
marketLength
|
|
);
|
|
for (int i = 0; i < marketLength; i++) {
|
|
oscStates[i] = emptyOscState;
|
|
}
|
|
|
|
//
|
|
XMAState emptyXmaState = {};
|
|
ArrayFree(xmaStates);
|
|
ArrayResize(
|
|
xmaStates,
|
|
shortCycleSlowMultiplier * marketLength
|
|
);
|
|
for (int i = 0; i < shortCycleSlowMultiplier * marketLength; i++) {
|
|
xmaStates[i] = emptyXmaState;
|
|
}
|
|
|
|
//
|
|
XMKTState emptyXmktState = {};
|
|
ArrayFree(xmktStates);
|
|
ArrayResize(
|
|
xmktStates,
|
|
marketLength
|
|
);
|
|
for (int i = 0; i < marketLength; i++) {
|
|
xmktStates[i] = emptyXmktState;
|
|
}
|
|
|
|
//
|
|
// Retrieve Bar Index Time ...
|
|
datetime barTime = iTime(
|
|
_Symbol,
|
|
_Period,
|
|
bar_index + 1
|
|
);
|
|
|
|
//
|
|
// START Retrieve Statets ...
|
|
//
|
|
//
|
|
// Loop through Market Length ...
|
|
int index = 0;
|
|
for (int i = bar_index; i < bar_index + marketLength; i++) {
|
|
//
|
|
// Retrieve Index OSC State ...
|
|
XOSCState oscState = GetOSCState(
|
|
i, // Bar Index ...
|
|
fastOSCLength,
|
|
fastOSCMultiplier,
|
|
slowOSCLength,
|
|
slowOSCMultiplier
|
|
);
|
|
|
|
//
|
|
// Retrieve XMarketState ...
|
|
XMKTState xmktState = GetMarketState(
|
|
//
|
|
i,
|
|
marketLength,
|
|
//
|
|
showHighestHigh,
|
|
highestHighColor,
|
|
highestHighStyle,
|
|
//
|
|
showHighestLow,
|
|
highestLowColor,
|
|
highestLowStyle,
|
|
//
|
|
showHighestOpen,
|
|
highestOpenColor,
|
|
highestOpenStyle,
|
|
//
|
|
showHighestClose,
|
|
highestCloseColor,
|
|
highestCloseStyle,
|
|
//
|
|
showLowestHigh,
|
|
lowestHighColor,
|
|
lowestHighStyle,
|
|
//
|
|
showLowestLow,
|
|
lowestLowColor,
|
|
lowestLowStyle,
|
|
//
|
|
showLowestOpen,
|
|
lowestOpenColor,
|
|
lowestOpenStyle,
|
|
//
|
|
showLowestClose,
|
|
lowestCloseColor,
|
|
lowestCloseStyle
|
|
);
|
|
|
|
//
|
|
// Set Retrieved Index States ...
|
|
oscStates[index] = oscState;
|
|
xmktStates[index] = xmktState;
|
|
|
|
//
|
|
index++;
|
|
}
|
|
|
|
index = 0;
|
|
for (int i = bar_index; i < bar_index + (shortCycleSlowMultiplier * marketLength); i++) {
|
|
//
|
|
// Retrieve XMA State ...
|
|
XMAState xmaState = GetXMAState(
|
|
i, // Bar Index ...
|
|
marketLength, // Market Length ...
|
|
step, // SAR Step ...
|
|
maximum, // SAR Maximum ...
|
|
shortCycleFastMultiplier, // Short Cycle Fast Multiplier ...
|
|
shortCycleSlowMultiplier, // Short Cycle Slow Multiplier ...
|
|
mediumCycleFastMultiplier, // Medium Cycle Fast Multiplier ...
|
|
mediumCycleSlowMultiplier, // Medium Cycle Slow Multiplier ...
|
|
longCycleFastMultiplier, // Long Cycle Fast Multiplier ...
|
|
longCycleSlowMultiplier, // Long Cycle Slow Multiplier ...
|
|
showPSar, // Show Parabolic Sar
|
|
showMarketMiddle, // Show Market Middle ...
|
|
showShortCycle, // Show Short Cycle
|
|
showShortCycleCrossLines, // Show Short Cycle Vertical Lines
|
|
showMediumCycle, // Show Medium Cycle
|
|
showMediumCycleCrossLines, // Show Medium Cycle Vertical Lines
|
|
showLongCycle, // Show Long Cycle
|
|
showLongCycleCrossLines, // Show Long Cycle Vertical Lines
|
|
pSarColor, // Parabolic Sar Color
|
|
shortCycleFastColor, // Short Cycle Fast Color ...
|
|
shortCycleSlowColor, // Short Cycle Slow Color ...
|
|
mediumCycleFastColor, // Medium Cycle Fast Color ...
|
|
mediumCycleSlowColor, // Medium Cycle Slow Color ...
|
|
longCycleFastColor, // Medium Cycle Fast Color ...
|
|
longCycleSlowColor // Medium Cycle Slow Color ...
|
|
);
|
|
|
|
//
|
|
xmaStates[index] = xmaState;
|
|
|
|
//
|
|
index++;
|
|
}
|
|
//
|
|
// END Retrieve Statets ...
|
|
//
|
|
|
|
//
|
|
// START States Calculations ...
|
|
//
|
|
|
|
//
|
|
// START OSC Calculations ...
|
|
//
|
|
//
|
|
// END OSC Calculations ...
|
|
//
|
|
|
|
//
|
|
// START XMA Calculations ...
|
|
//
|
|
|
|
//
|
|
// END XMA Calculations ...
|
|
//
|
|
|
|
//
|
|
// START Momentum Calculations ...
|
|
//
|
|
//
|
|
// END Momentum Calculations ...
|
|
//
|
|
|
|
//
|
|
// START RSI Calculations ...
|
|
//
|
|
//
|
|
// END RSI Calculations ...
|
|
//
|
|
|
|
//
|
|
// START PRICE Calculations ...
|
|
//
|
|
RefreshRates();
|
|
|
|
//
|
|
double marketLow[];
|
|
double marketOpen[];
|
|
double marketHigh[];
|
|
double marketClose[];
|
|
//
|
|
double marketUp[];
|
|
double marketDown[];
|
|
//
|
|
ArrayResize(
|
|
marketLow,
|
|
marketLength
|
|
);
|
|
ArrayResize(
|
|
marketOpen,
|
|
marketLength
|
|
);
|
|
ArrayResize(
|
|
marketHigh,
|
|
marketLength
|
|
);
|
|
ArrayResize(
|
|
marketClose,
|
|
marketLength
|
|
);
|
|
//
|
|
ArrayResize(
|
|
marketUp,
|
|
marketLength
|
|
);
|
|
ArrayResize(
|
|
marketDown,
|
|
marketLength
|
|
);
|
|
|
|
//
|
|
index = 0;
|
|
for (int i = bar_index; i < marketLength + bar_index; i++) {
|
|
//
|
|
marketLow[index] = iLow(
|
|
_Symbol,
|
|
_Period,
|
|
i
|
|
);
|
|
|
|
//
|
|
marketOpen[index] = iOpen(
|
|
_Symbol,
|
|
_Period,
|
|
i
|
|
);
|
|
|
|
//
|
|
marketHigh[index] = iHigh(
|
|
_Symbol,
|
|
_Period,
|
|
i
|
|
);
|
|
|
|
//
|
|
marketClose[index] = iClose(
|
|
_Symbol,
|
|
_Period,
|
|
i
|
|
);
|
|
|
|
//
|
|
// marketUp[i] = MathMax(marketOpen[i], marketClose[i]);
|
|
marketUp[index] = marketHigh[i];
|
|
|
|
//
|
|
// marketDown[i] = MathMin(marketOpen[i], marketClose[i]);
|
|
marketDown[index] = marketLow[i];
|
|
|
|
//
|
|
index++;
|
|
}
|
|
|
|
//
|
|
// LONG Prices ...
|
|
double longEntryPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
|
|
double longClosePrice = SymbolInfoDouble(_Symbol, SYMBOL_BID);
|
|
double longPriceGap = longClosePrice - longEntryPrice;
|
|
|
|
//
|
|
// SHORT Prices ...
|
|
double shortEntryPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID);
|
|
double shortClosePrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
|
|
double shortPriceGap = shortEntryPrice - shortClosePrice;
|
|
|
|
//
|
|
if (startMarketTime == 0) {
|
|
startMarketTime = barTime;
|
|
}
|
|
|
|
//
|
|
int startBarIndex = iBarShift(
|
|
_Symbol,
|
|
_Period,
|
|
startMarketTime
|
|
);
|
|
|
|
//
|
|
if (startBarIndex > bar_index + marketLength) {
|
|
//
|
|
startBarIndex = 0;
|
|
startMarketTime = 0;
|
|
}
|
|
|
|
//
|
|
bool isSharpBullishDetected = false;
|
|
bool isShareBearishDetected = false;
|
|
double sharpDetectionValue = sharpDetectMultiplier * _Point;
|
|
if (startBarIndex > bar_index + 1) {
|
|
//
|
|
double marketStartHigh = iHigh(
|
|
_Symbol,
|
|
_Period,
|
|
startBarIndex
|
|
);
|
|
|
|
double marketStartLow = iLow(
|
|
_Symbol,
|
|
_Period,
|
|
startBarIndex
|
|
);
|
|
|
|
//
|
|
double prevCandleOpen = iOpen(
|
|
_Symbol,
|
|
_Period,
|
|
bar_index + 1
|
|
);
|
|
|
|
//
|
|
double prevCandleHigh = iHigh(
|
|
_Symbol,
|
|
_Period,
|
|
bar_index + 1
|
|
);
|
|
|
|
//
|
|
double prevCandleClose = iClose(
|
|
_Symbol,
|
|
_Period,
|
|
bar_index + 1
|
|
);
|
|
|
|
//
|
|
double candleOpen = iOpen(
|
|
_Symbol,
|
|
_Period,
|
|
bar_index
|
|
);
|
|
|
|
//
|
|
double prevCandleComparedPrice = MathMin(prevCandleOpen, prevCandleClose);
|
|
isShareBearishDetected =
|
|
prevCandleHigh < marketStartHigh
|
|
&& prevCandleComparedPrice < marketStartHigh
|
|
&& marketStartHigh - prevCandleComparedPrice >= sharpDetectionValue;
|
|
|
|
// //
|
|
// isSharpBullishDetected =
|
|
// marketStartHigh - MathMin(prevCandleOpen, prevCandleClose) >= sharpDetectionValue;
|
|
}
|
|
//
|
|
if (
|
|
isShareBearishDetected
|
|
|| isSharpBullishDetected
|
|
) {
|
|
startBarIndex = 0;
|
|
startMarketTime = 0;
|
|
}
|
|
//
|
|
//
|
|
// END PRICE Calculations ...
|
|
//
|
|
|
|
//
|
|
// START Capturing Signal ...
|
|
//
|
|
|
|
//
|
|
// START LONG Signals ...
|
|
//
|
|
//
|
|
// NOTES:
|
|
// when MC Fast is Over MC Slow,
|
|
// All Long Trades must be down when Market Middle is above MCSlow ...
|
|
// and must be paused when Market Middle is Going Under MCSlow ...
|
|
|
|
//
|
|
// OSC ...
|
|
bool oscHasLongSignal = false;
|
|
if (useOSCSignalling) {
|
|
//
|
|
oscHasLongSignal =
|
|
true
|
|
&& (
|
|
oscStates[0].fastOSC < 0
|
|
)
|
|
;
|
|
}
|
|
|
|
//
|
|
// XMA ...
|
|
bool xmaHasLongSignal = false;
|
|
if (useXMASignalling) {
|
|
//
|
|
xmaHasLongSignal =
|
|
//
|
|
// Long Cycle Trend Up ...
|
|
xmaStates[0].lcFast > xmaStates[0].lcSlow
|
|
// Lowest Low Must be Higher than lcFast ...
|
|
&& xmktStates[0].lowestLow > xmaStates[0].lcFast
|
|
//
|
|
// Medium Cycle in Up Trend ...
|
|
&& xmaStates[0].mcFast > xmaStates[0].mcSlow
|
|
//
|
|
// and the Medium Cycle Distance must be at least 100 Point ...
|
|
&& (xmaStates[0].mcFast - xmaStates[0].mcSlow) > (100 * _Point)
|
|
//
|
|
// then looking for parabolic sar cross down market middleage ...
|
|
&& xmaStates[0].parabolicSAR < xmaStates[0].marketMiddleage
|
|
&& !(xmaStates[1].parabolicSAR <= xmaStates[1].marketMiddleage)
|
|
//
|
|
&& xmaStates[0].scFast > xmaStates[0].marketMiddleage
|
|
//
|
|
// in crossing time Parabolic SAR must be greater than mcFast ...
|
|
&& xmaStates[0].parabolicSAR > xmaStates[0].mcFast
|
|
//
|
|
// in this conditions, entry price must below than highest high, in market ...
|
|
&& longEntryPrice < xmktStates[0].highestHigh
|
|
;
|
|
}
|
|
|
|
//
|
|
bool xshpHasLongSignal = false;
|
|
if (useXSHPSignalling) {
|
|
//
|
|
xshpHasLongSignal =
|
|
//
|
|
isShareBearishDetected
|
|
//
|
|
&& xmaStates[0].mcFast > xmaStates[0].mcSlow
|
|
&& xmaStates[1].mcFast > xmaStates[1].mcSlow
|
|
&& xmaStates[2].mcFast > xmaStates[3].mcSlow
|
|
//
|
|
&& xmaStates[1].mcFast - xmaStates[1].mcSlow > (100 * _Point)
|
|
//
|
|
&& xmktStates[1].lowestLow > xmaStates[1].mcSlow
|
|
&& xmktStates[1].highestLow > xmktStates[1].lowestHigh
|
|
&& MathAbs(xmktStates[0].highestLow - xmktStates[0].lowestHigh) > (50 * _Point)
|
|
//
|
|
&& longEntryPrice != xmktStates[0].lowestHigh
|
|
&& MathAbs(longEntryPrice - xmktStates[0].lowestHigh) > (50 * _Point)
|
|
//
|
|
&& (xmaStates[0].marketMiddleage > xmaStates[0].mcFast
|
|
|| (
|
|
xmaStates[0].marketMiddleage > xmaStates[0].mcSlow
|
|
&& xmaStates[0].marketMiddleage < xmaStates[0].mcFast
|
|
)
|
|
) ?
|
|
!(longEntryPrice < xmaStates[0].mcSlow)
|
|
&& !(
|
|
longEntryPrice > xmaStates[0].mcSlow
|
|
&& longEntryPrice < xmaStates[0].mcFast
|
|
) :
|
|
true
|
|
;
|
|
}
|
|
|
|
//
|
|
bool xmntmHasLongSignal = false;
|
|
if (useXMNTMSignalling) {
|
|
}
|
|
|
|
//
|
|
bool xrsiHasLongSignal = false;
|
|
if (useXRSISignalling) {
|
|
}
|
|
|
|
//
|
|
bool hasLongSignal =
|
|
//
|
|
// OSC Signals ...
|
|
oscHasLongSignal
|
|
|| xmaHasLongSignal
|
|
|| xshpHasLongSignal
|
|
|| xmntmHasLongSignal
|
|
|| xrsiHasLongSignal
|
|
;
|
|
//
|
|
// END LONG Signals ...
|
|
//
|
|
|
|
//
|
|
// START SHORT Signals ...
|
|
//
|
|
bool hasShortSignal = false;
|
|
//
|
|
// END SHORT Signals ...
|
|
//
|
|
|
|
//
|
|
// Check Signal Exists regardless of Long or Short ...
|
|
bool hasSignal = hasLongSignal || hasShortSignal;
|
|
|
|
// //
|
|
// // Check Short Cycle For Double Crossing ...
|
|
// int scCrosses = 0;
|
|
// int pSarCrosses = 0;
|
|
|
|
// //
|
|
// // SC Crosses ...
|
|
// for (int i = bar_index; i < bar_index + (shortCycleSlowMultiplier * marketLength) - 1; i++) {
|
|
// //
|
|
// bool isPSarCrossUnderMarketMid =
|
|
// xmaStates[0].parabolicSAR < xmaStates[0].marketMiddleage
|
|
// && !(xmaStates[1].parabolicSAR < xmaStates[1].marketMiddleage);
|
|
|
|
// //
|
|
// bool isPSarCrossOverMarketMid =
|
|
// xmaStates[0].parabolicSAR > xmaStates[0].marketMiddleage
|
|
// && !(xmaStates[1].parabolicSAR > xmaStates[1].marketMiddleage);
|
|
|
|
// //
|
|
// if (
|
|
// isPSarCrossUnderMarketMid
|
|
// || isPSarCrossOverMarketMid
|
|
// ) {
|
|
// pSarCrosses++;
|
|
// }
|
|
|
|
// //
|
|
// bool isSCFastCrossOverSlow =
|
|
// xmaStates[i].scFast > xmaStates[i].scSlow
|
|
// && !(xmaStates[i].scFast > xmaStates[i].scSlow);
|
|
|
|
// //
|
|
// bool isSCFastCrossUnderSlow =
|
|
// xmaStates[i].scFast < xmaStates[i].scSlow
|
|
// && !(xmaStates[i].scFast < xmaStates[i].scSlow);
|
|
|
|
// //
|
|
// if (
|
|
// isSCFastCrossOverSlow
|
|
// || isSCFastCrossUnderSlow
|
|
// ) {
|
|
// scCrosses++;
|
|
// }
|
|
// }
|
|
|
|
// //
|
|
// // Parabolic SAR ...
|
|
// for (int i = bar_index; i < bar_index + (shortCycleFastMultiplier * marketLength) - 1; i++) {
|
|
// //
|
|
// bool isPSarCrossUnderMarketMid =
|
|
// xmaStates[0].parabolicSAR < xmaStates[0].marketMiddleage
|
|
// && !(xmaStates[1].parabolicSAR < xmaStates[1].marketMiddleage);
|
|
|
|
// //
|
|
// bool isPSarCrossOverMarketMid =
|
|
// xmaStates[0].parabolicSAR > xmaStates[0].marketMiddleage
|
|
// && !(xmaStates[1].parabolicSAR > xmaStates[1].marketMiddleage);
|
|
|
|
// //
|
|
// if (
|
|
// isPSarCrossUnderMarketMid
|
|
// || isPSarCrossOverMarketMid
|
|
// ) {
|
|
// pSarCrosses++;
|
|
// }
|
|
// }
|
|
|
|
// //
|
|
// if (
|
|
// scCrosses > 1
|
|
// || pSarCrosses > 1
|
|
// ) {
|
|
// LogMessage("Crosses Exceed ...");
|
|
// hasSignal = false;
|
|
// }
|
|
|
|
//
|
|
// Prevent from Going forward if there is not a Signal ...
|
|
if (!hasSignal) {
|
|
//
|
|
result.signal = signal;
|
|
return result;
|
|
}
|
|
|
|
//
|
|
totalSignals++;
|
|
|
|
//
|
|
// Define Price Related Variables ...
|
|
//
|
|
double price = 0;
|
|
double priceGap = 0;
|
|
double sl = 0;
|
|
double risk;
|
|
double reward;
|
|
double tp = 0;
|
|
double r2rRatio = riskToRewardRatio;
|
|
|
|
//
|
|
datetime time = iTime(
|
|
_Symbol,
|
|
_Period,
|
|
bar_index
|
|
);
|
|
|
|
//
|
|
// Fill Signal Related Variables ...
|
|
if (hasLongSignal) {
|
|
//
|
|
price = longEntryPrice;
|
|
priceGap = longPriceGap;
|
|
|
|
//
|
|
// Setting Up SL Based on Last Market Lowest ...
|
|
sl = GetMarketLowestLow(
|
|
bar_index,
|
|
marketLength
|
|
);
|
|
|
|
//
|
|
risk = price - sl;
|
|
if (risk > (MathAbs(xmaStates[0].mcFast - xmaStates[0].mcSlow) / 2)) {
|
|
risk = risk / 3;
|
|
}
|
|
|
|
reward = risk * r2rRatio;
|
|
tp = price + reward;
|
|
|
|
//
|
|
// Check TP based on Spread ...
|
|
if (tp < price + priceGap) {
|
|
tp = tp + priceGap;
|
|
}
|
|
|
|
//
|
|
sl = 0;
|
|
|
|
//
|
|
totalLongSignals++;
|
|
} else if (hasShortSignal) {
|
|
//
|
|
totalShortSignals++;
|
|
|
|
//
|
|
price = shortEntryPrice;
|
|
priceGap = shortPriceGap;
|
|
|
|
//
|
|
risk = sl - price;
|
|
reward = risk * r2rRatio;
|
|
tp = price - reward;
|
|
}
|
|
|
|
//
|
|
// Normalize Prices ...
|
|
price = NormalizeDouble(price, _Digits);
|
|
sl = NormalizeDouble(sl, _Digits);
|
|
tp = NormalizeDouble(tp, _Digits);
|
|
|
|
//
|
|
// Generate Signal Structure ...
|
|
signal.type = hasLongSignal ?
|
|
X_LONG :
|
|
X_SHORT;
|
|
signal.tp = tp;
|
|
signal.sl = sl;
|
|
signal.time = time;
|
|
signal.symbol = _Symbol;
|
|
signal.entryPrice = price;
|
|
signal.id = totalLongSignals;
|
|
//
|
|
// TODO: Fill Signal Comment By Sgnal Provider
|
|
signal.comment =
|
|
useOSCSignalling && oscHasLongSignal
|
|
? oscSignalIdentifier
|
|
: useXMASignalling && xmaHasLongSignal
|
|
? xmaSignalIdentifier
|
|
: useXSHPSignalling && xshpHasLongSignal
|
|
? xshpSignalIdentifier
|
|
: useXMNTMSignalling && xmntmHasLongSignal
|
|
? xmntmSignalIdentifier
|
|
: useXRSISignalling && xrsiHasLongSignal
|
|
? xrsiSignalIdentifier
|
|
: ""
|
|
;
|
|
//
|
|
// END Capturing Signal ...
|
|
//
|
|
|
|
//
|
|
// Fill Result ...
|
|
result.hasSignal = hasSignal;
|
|
result.signal = signal;
|
|
result.type = signal.type;
|
|
|
|
//
|
|
// Return Result ...
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check State for Signal Handling ...
|
|
void CheckState() {
|
|
//
|
|
// Here we Must to Check Market State for enable or disable
|
|
// Signal Handlers and also make dection to close all long/short
|
|
// trades ...
|
|
|
|
//
|
|
// Prevent from Checking, if there is no states available ...
|
|
if (ArraySize(xmaStates) == 0) {
|
|
return;
|
|
}
|
|
|
|
// //
|
|
// closeLongTrades =
|
|
// xmaStates[0].parabolicSAR > xmaStates[0].marketMiddleage
|
|
// && !(xmaStates[1].parabolicSAR > xmaStates[1].marketMiddleage)
|
|
// ;
|
|
|
|
// //
|
|
// closeLongTrades =
|
|
// false
|
|
// ;
|
|
}
|
|
|
|
//
|
|
// Calculate Signals and Process Based on Exists Signals ...
|
|
void ProcessSignals() {
|
|
//
|
|
XSignalRequest request = {};
|
|
request.type = X_NONE;
|
|
request.hasSignal = false;
|
|
|
|
//
|
|
// Prevent Multiple Calculating on Same Bars ...
|
|
isNewBar = IsNewBar();
|
|
if (isNewBar) {
|
|
//
|
|
countedBars++;
|
|
}
|
|
|
|
//
|
|
bool allowDoTrade = true;
|
|
|
|
//
|
|
// Check Balance ...
|
|
if (initialBalance > 0) {
|
|
//
|
|
// Retrieve Account Balance ...
|
|
double balance = AccountInfoDouble(ACCOUNT_BALANCE);
|
|
double minimumBalanceForTrade =
|
|
balance > initialBalance
|
|
?
|
|
minBalancePercent * balance
|
|
:
|
|
minBalancePercent * initialBalance;
|
|
|
|
//
|
|
// Retrieve Account Equity ...
|
|
double equity = AccountInfoDouble(ACCOUNT_EQUITY);
|
|
double maxAllowedEquity = balance - (balance * maxEquityPercent);
|
|
|
|
//
|
|
// Retrieve Free Marigin ...
|
|
double freeMargin = AccountFreeMargin();
|
|
double maximumMariginRisk = balance - (balance * maxEquityPercent);
|
|
|
|
//
|
|
if (
|
|
//
|
|
// Do not Open Positions if equity not passed ...
|
|
equity < maxAllowedEquity ||
|
|
//
|
|
// Do not Open Positions if free margin not passed ...
|
|
freeMargin <= maximumMariginRisk ||
|
|
//
|
|
// Do not open positions if balance less than minimum ...
|
|
balance <= minimumBalanceForTrade
|
|
) {
|
|
//
|
|
allowDoTrade = false;
|
|
|
|
// //
|
|
// string message = StringConcatenate(
|
|
// "Trading Pause => ",
|
|
// "Balance: ", balance,
|
|
// ", Equity: ", equity,
|
|
// ", FreeMargin: ", freeMargin
|
|
// );
|
|
|
|
// //
|
|
// LogMessage(message);
|
|
// SendAlert(message);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Retrieve Signal Exists ...
|
|
request = GenerateSignal(0);
|
|
|
|
//
|
|
// Prevent doing anything else, if there is no signals ...
|
|
if (
|
|
!allowDoTrade ||
|
|
!request.hasSignal ||
|
|
request.type == X_NONE
|
|
) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
bool hasLongSignal = request.type == X_LONG;
|
|
|
|
//
|
|
// Check For Bot State ...
|
|
if (
|
|
(hasLongSignal && !waitForLongSignals)
|
|
|| (!hasLongSignal && !waitForShortSignals)
|
|
) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Check last Signalled Bar with Counted Bars ...
|
|
// Prevent Multiple Signalling on Same Bar ...
|
|
bool isInLastSignalledBars = false;
|
|
for (int i=0; i < marketLength; i++) {
|
|
//
|
|
isInLastSignalledBars =
|
|
isInLastSignalledBars
|
|
|| lastSignalledBar == countedBars - i
|
|
;
|
|
}
|
|
if (isInLastSignalledBars) {
|
|
//
|
|
totalSignals--;
|
|
if (hasLongSignal) {
|
|
totalLongSignals--;
|
|
} else {
|
|
totalShortSignals--;
|
|
}
|
|
return;
|
|
}
|
|
|
|
//
|
|
// increase last signalled bar ...
|
|
lastSignalledBar = countedBars;
|
|
|
|
//
|
|
// Calculate Can Trade or not ...
|
|
allowDoTrade = allowTrade
|
|
&& (
|
|
hasLongSignal ?
|
|
allowLongTrades :
|
|
allowShortTrades
|
|
);
|
|
|
|
//
|
|
// Chack Maximum Open Positions ...
|
|
int openTrades = CountOpenTrades();
|
|
if (maxOpenTrades > 0) {
|
|
//
|
|
if (openTrades >= maxOpenTrades) {
|
|
//
|
|
allowDoTrade = false;
|
|
|
|
//
|
|
if (closeAllInProfitOpenTradesWhenMaxOpenTradesReached) {
|
|
//
|
|
// Close All In Profit Trades ...
|
|
bool hasClosedInProfitTrade = CloseAllInProfitTrades();
|
|
if (hasClosedInProfitTrade) {
|
|
//
|
|
openTrades = CountOpenTrades();
|
|
|
|
//
|
|
allowDoTrade = !(openTrades >= maxOpenTrades);
|
|
}
|
|
}
|
|
|
|
//
|
|
if (!allowDoTrade) {
|
|
//
|
|
string message = StringConcatenate(
|
|
"Trading Pause => ",
|
|
"Max Open Trades (",
|
|
maxOpenTrades,
|
|
") reached ..."
|
|
);
|
|
|
|
//
|
|
LogMessage(message);
|
|
SendAlert(message);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Check Trading is Enable or not ...
|
|
// nothing to do if trading is disabled ...
|
|
if (!allowDoTrade) {
|
|
// //
|
|
// string message = StringConcatenate(
|
|
// "Trading Not Allowed ..."
|
|
// );
|
|
|
|
// //
|
|
// LogMessage(message);
|
|
// SendAlert(message);
|
|
return;
|
|
}
|
|
|
|
//
|
|
bool isPositionOpened = TradeSignal(
|
|
request.signal,
|
|
signalPrefix,
|
|
lotsPerTradePercent,
|
|
//
|
|
bullishSignalLabel,
|
|
bullishSignalColor,
|
|
bearishSignalLabel,
|
|
bearishSignalColor,
|
|
//
|
|
// Signal Identifiers ...
|
|
oscSignalIdentifier,
|
|
xmaSignalIdentifier,
|
|
xshpSignalIdentifier,
|
|
xmntmSignalIdentifier,
|
|
xrsiSignalIdentifier
|
|
);
|
|
|
|
//
|
|
if (isPositionOpened) {
|
|
//
|
|
bool canAlert =
|
|
alertPositions
|
|
&& (
|
|
hasLongSignal ?
|
|
longPositionAlerts
|
|
:
|
|
shortPositionAlerts
|
|
);
|
|
|
|
//
|
|
if (canAlert) {
|
|
//
|
|
// Alert Message ...
|
|
string message = StringConcatenate(
|
|
"Trade on Signal ID: ", request.signal.id,
|
|
", Entry: ", request.signal.entryPrice,
|
|
", TP: ", request.signal.tp
|
|
);
|
|
|
|
//
|
|
// Terminal Alert ...
|
|
if (terminalAlert) {
|
|
Alert(message);
|
|
}
|
|
|
|
//
|
|
// Push Alert ...
|
|
if (pushAlert) {
|
|
SendNotification(message);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Process All Open Positions ...
|
|
void ProcessOpenPositions() {
|
|
//
|
|
// this comes from check state ...
|
|
if (closeLongTrades) {
|
|
//
|
|
closeLongTrades = false;
|
|
|
|
//
|
|
bool isAllLongTradesClosed = CloseAllLongTrades();
|
|
if (isAllLongTradesClosed) {
|
|
// waitForLongSignals = false;
|
|
}
|
|
}
|
|
|
|
//
|
|
// this comes from check state ...
|
|
if (closeShortTrades) {
|
|
//
|
|
closeShortTrades = false;
|
|
|
|
//
|
|
bool isAllShortTradesClosed = CloseAllShortTrades();
|
|
if (isAllShortTradesClosed) {
|
|
// waitForShortSignals = false;
|
|
}
|
|
}
|
|
|
|
//
|
|
bool hasClosedLongTimeTrade = CloseAllLongTimeTrades(
|
|
closeAllOpenTradesAfterCandle
|
|
);
|
|
|
|
//
|
|
// Close Maximum DrawDown Passed Trades ...
|
|
bool hasClosedInDrawDownLongTrade = CloseAllMaximumDrawDownPassedTrades(
|
|
maxDrawdownPercentPerPTrade
|
|
);
|
|
|
|
//
|
|
if (
|
|
hasClosedLongTimeTrade
|
|
|| hasClosedInDrawDownLongTrade
|
|
) {
|
|
//
|
|
// waitForLongSignals = false;
|
|
// waitForShortSignals = false;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Send Special Type of Alerts ...
|
|
void SendAlert(string message) {
|
|
//
|
|
if (!alertEvents) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Terminal Alert ...
|
|
if (terminalAlert) {
|
|
Alert(message);
|
|
}
|
|
|
|
//
|
|
// Push Alert ...
|
|
if (pushAlert) {
|
|
SendNotification(message);
|
|
}
|
|
}
|
|
//
|
|
// END Functions ...
|
|
// |