//+------------------------------------------------------------------+ //| 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; }