Files
MQL4Data/Bkp/Used/14020420/x-saherelm.cci.ea.mq4
2024-01-25 04:05:58 +03:30

532 lines
9.7 KiB
Plaintext

//+------------------------------------------------------------------+
//| x-saherelm.ea |
//| Copyright 2023, SaherElm IT Center |
//| https://www.saherelm.ir |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, SaherElm IT Center"
#property link "https://www.saherelm.ir"
#property version "1.00"
#property strict
//
// Inputs ...
input double riskToReward = 1.5; // Risk To Reward Ratio
//
// Define Models ...
//
// Signal Providers ...
enum ENUM_XSIGNAL_PROVIDER {
X_UNKNOWN_PROVIDER = 0,
X_CCI_PROVIDER = 1
};
//
// Signal Type ...
enum ENUM_XSIGNAL_TYPE {
X_NONE = 0,
X_BUY = 1,
X_SELL = 2
};
//
// Signal ...
struct XSignal {
//
// Signal Type ...
ENUM_XSIGNAL_TYPE type;
//
// Signal ID ...
int id;
//
// Signal Ticket Number, when Opening Trade ...
int ticket;
//
// Signal Provider ...
ENUM_XSIGNAL_PROVIDER provider;
//
// Target Point ...
double tp;
//
// Stop Loss ...
double sl;
//
// Signal Entry Price ...
double price;
//
// Signalling Time ...
datetime time;
};
//
// CCI Based Signal Conditions ...
struct XCCILongSignalConditions {
//
datetime start;
//
datetime crossOverMinusHundredTime;
datetime crossUnderMinusHundredTime;
//
double crossOverSlope;
};
//
bool isNewBar = false;
//
int countedBars = 0;
int totalSignals = 0;
int lastSignalledBar = 0;
//
XCCILongSignalConditions cciLongConds = {};
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
//
isNewBar = IsNewBar();
//
if (isNewBar) {
//
countedBars++;
}
//
datetime barTime = iTime(
_Symbol,
_Period,
0
);
//
bool hasSignal = false;
bool hasLongSignal = false;
bool hasShortSignal = false;
//
// Generate Signals Based On iCCI ...
CheckCCILongSignalConditions(0);
//
// Long Signal ...
hasLongSignal =
//
// Check CCI Long Signal is Valid ...
ValidateCCILongConditions();
//
// Signal ...
hasSignal = hasLongSignal || hasShortSignal;
//
// Prevent Going Forward when there is no Signal ...
if (!hasSignal) {
return;
}
//
if (lastSignalledBar == countedBars) {
return;
}
//
totalSignals++;
lastSignalledBar = countedBars;
//
// Get CCI Long Signal ...
XSignal signal = {};
//
if (hasLongSignal) {
signal = GenerateCCILongSignal();
}
//
TradeOnSignal(signal);
//
Print("CCI Long Signal ...");
//
ClearCCILongSignalConditions();
}
//
// Trade Based On Signal ...
void TradeOnSignal(
XSignal &signal
) {
//
if (signal.type == X_NONE) {
return;
}
//
bool isLongSignal = signal.type == X_BUY;
//
// Order Operation ...
int operation = isLongSignal ?
OP_BUY :
OP_SELL;
//
// Detect Trade Color ...
color clr = isLongSignal ?
clrAqua :
clrFuchsia;
//
// Generate Signal Comment ...
string label = isLongSignal ?
"BUY" :
"SELL";
//
// Generate Signal Comment ...
string comment = StringConcatenate(
"XCCI",
"_", signal.id,
"_", label
);
//
// Placing Order ...
int orderTicket = OrderSend(
_Symbol,
operation,
0.01,
signal.price,
3,
signal.sl,
signal.tp,
comment,
signal.id,
0,
clr
);
//
// Draw Signal Shape if Order Opened Successfully ...
if (orderTicket >= 0) {
//
signal.ticket = orderTicket;
Print("Order: ", orderTicket, " ...");
}
}
//
// Convert CCI Long Signal Conditions to XSignal ...
XSignal GenerateCCILongSignal() {
//
XSignal result = {};
//
// Price Calculations ...
//
RefreshRates();
//
double entryPrice = SymbolInfoDouble(
_Symbol,
SYMBOL_ASK
);
//
double exitPrice = SymbolInfoDouble(
_Symbol,
SYMBOL_BID
);
//
double priceGap = MathAbs(entryPrice - exitPrice);
//
double ll = GetLowestLow();
double hh = GetHighestHigh();
double pSar = iSAR(
_Symbol,
_Period,
0.002,
0.02,
0
);
//
double sl = ll;
//
double risk = entryPrice - ll;
double reward = risk * riskToReward;
//
double tp = entryPrice + reward;
//
if (tp > hh) {
tp = hh;
}
//
if (tp < entryPrice + priceGap) {
tp = entryPrice + priceGap;
}
//
datetime barTime = iTime(
_Symbol,
_Period,
0
);
//
result.tp = tp;
result.sl = 0; // sl;
result.type = X_BUY;
result.id = totalSignals;
result.price = entryPrice;
result.provider = X_CCI_PROVIDER;
result.time = barTime;
//
return result;
}
//
// Validate CCI Signal Conditions ...
bool ValidateCCILongConditions() {
//
bool result =
cciLongConds.start != 0
&& cciLongConds.crossUnderMinusHundredTime != 0
&& cciLongConds.crossOverMinusHundredTime != 0
&& cciLongConds.crossUnderMinusHundredTime >= cciLongConds.start
&& cciLongConds.crossOverMinusHundredTime > cciLongConds.crossUnderMinusHundredTime
&& cciLongConds.crossOverSlope > 0;
//
return result;
}
//
// Clear CCI Long Signal Conditions for New One ...
void ClearCCILongSignalConditions() {
//
cciLongConds.start = 0;
cciLongConds.crossOverSlope = 0;
cciLongConds.crossOverMinusHundredTime = 0;
cciLongConds.crossUnderMinusHundredTime = 0;
}
//
// Check and Fill CC Signal Conditions ...
void CheckCCILongSignalConditions(
const int bar_index
) {
//
// Retrieve Bar Time ...
datetime barTime = iTime(
_Symbol,
_Period,
bar_index
);
//
// LONG:
// wait for cci cross under -100
// then wait for cross over -100
// slope of crossing over ??? ...
if (cciLongConds.start == 0) {
cciLongConds.start = barTime;
}
//
// Check Start Time ...
if (cciLongConds.start == 0) {
return;
}
//
// Read current, prev, and prevPrev CCI ...
double cci = GetCCI(bar_index);
double cci1 = GetCCI(bar_index + 1);
double cci2 = GetCCI(bar_index + 2);
//
// Find Cross Under -100 ...
bool isCrossUnderMinusHundred =
cci < -100 && !(cci1 < -100);
//
// Fill Conditions ...
if (
isCrossUnderMinusHundred
&& cciLongConds.crossUnderMinusHundredTime == 0
) {
//
cciLongConds.crossUnderMinusHundredTime = barTime;
}
//
// Prevent Going forward untill Cross Under Happens ...
if (cciLongConds.crossUnderMinusHundredTime == 0) {
return;
}
//
// Find Cross Over -100 ...
bool isCrossOverMinusHundred =
cci > -100 && !(cci1 > -100);
//
// Fill Conditions ...
if (
isCrossOverMinusHundred
&& cciLongConds.crossOverMinusHundredTime == 0
) {
//
cciLongConds.crossOverMinusHundredTime = barTime;
}
//
// Prevent from Going forward untill Cross Over Happens ...
if (cciLongConds.crossOverMinusHundredTime == 0) {
return;
}
//
// Calculate Slope ...
double x1 = 0;
double y1 = cci1;
double x2 = 1;
double y2 = cci;
//
// Calculat Line Slope ...
double tSlope = GetSlope(
x1, y1, x2, y2
);
//
cciLongConds.crossOverSlope = tSlope;
}
//
// Retrieve CCI Value ...
double GetCCI(
const int bar_index,
const int marketLength = 504,
const ENUM_APPLIED_PRICE source = PRICE_TYPICAL
) {
//
double result = iCCI(
_Symbol,
_Period,
marketLength,
source,
bar_index
);
//
return result;
}
//
// Determines current working is New Bar or not ...
bool IsNewBar() {
//
static datetime lastbar;
datetime curbar = (datetime)SeriesInfoInteger(_Symbol, _Period, SERIES_LASTBAR_DATE);
//
if(lastbar != curbar) {
//
lastbar = curbar;
return true;
}
//
return false;
}
//
// Get Slope of a Line by it's two Point ...
double GetSlope(
double x1,
double y1,
double x2,
double y2
) {
//
double result = (y2 - y1)/(x2 - x1);
return result;
}
//
// Market Related Functions ...
//
double GetLowestLow() {
//
int index = iLowest(
_Symbol,
_Period,
MODE_LOW,
14,
0
);
//
double result = iLow(
_Symbol,
_Period,
index
);
//
return result;
}
//
double GetHighestHigh() {
//
int index = iHighest(
_Symbol,
_Period,
MODE_HIGH,
14,
0
);
//
double result = iHigh(
_Symbol,
_Period,
index
);
//
return result;
}