Code
// BogieNN_v8_Zorro.c
// -----------------------------------------------------------------------------
// Self-contained Zorro lite-C reconstruction of Bogie-NN-v8 + Bogie-NN-IND-v8.
//
// Signal path preserved from the supplied MQL4 sources:
//   H1 OHLC -> 12-bar NOC normalization -> EMA(5)
//   -> 17 lagged inputs (offsets 2..18 in indicator space)
//   -> neural net 17 -> 17 -> 5 -> 1, sigmoid activations
//   -> output 0..100
//   -> BUY on upward cross of 54, SELL on downward cross of 74.
//
// Trade logic preserved:
//   - one position at a time
//   - default SL 200 pips, TP disabled, trailing distance 170 pips
//   - opposite signal closes/reverses
//   - no-trade-day behavior preserves the original asymmetry:
//       long positions close on a no-trade day, short positions do not
//   - MT4-style money management is mapped to Zorro Amount, where Amount=1
//     is approximately one standard FX lot (100,000 units).
//
// Important source correction:
//   The MQL4 source declared gda_128[305] but writes indices 0..305.
//   The mathematically correct first-layer parameter count is 306, used here.
// -----------------------------------------------------------------------------

// ----------------------------- User settings ---------------------------------
string BogieAsset = "EUR/USD";

int UseMM = 1;
int MiniAcct = 0;
var RiskPercent = 5.0;
var FixedAmount = 0.0;      // MT4-style standard lots when UseMM == 0

var TakeProfitPips = 0.0;
var StopLossPips = 200.0;
var TrailingStopPips = 170.0;

var BuyTrigger = 54.0;
var SellTrigger = 74.0;

// MQL4 DayOfWeek: Sunday=0, Monday=1, ..., Saturday=6.
// These inputs intentionally retain that numbering.
int NoTradeDay_1 = 0;
int NoTradeDay_2 = 0;

// Original code used 5*Point as the minimum stop adjustment.
// On a typical 5-digit FX quote, that is 0.5 pip. Set to 5.0 for an old 4-digit
// quote if strict historical emulation is required.
var TrailGuardPips = 0.5;

// Indicator constants from Bogie-NN-IND-v8.
int NocPeriod = 12;
var NocMinRange = 0.012;
int EmaPeriod = 5;

// -------------------------- Embedded NN parameters ----------------------------
var W1[306] = {
   0.376436, 0.690657, 0.512335, 0.786179, 0.671377, 0.614279,
   0.53975, 0.82038, 0.750566, 0.70789, 0.396094, 0.72572,
   0.555349, 0.395257, 0.22728, 0.128274, 0.289072, 0.387067,
   0.66245, 1.019812, 0.761206, 0.98428, 0.878235, 0.829384,
   0.786234, 1.189799, 1.112219, 1.069424, 0.640762, 0.73067,
   0.067006, -0.320953, -0.60088, -0.371686, 0.261142, 0.063323,
   0.413053, 0.737687, 0.555759, 0.815068, 0.692078, 0.630406,
   0.556191, 0.84638, 0.763236, 0.715549, 0.390297, 0.705948,
   0.482014, 0.291501, 0.101741, 0.048724, 0.280508, 0.428389,
   -6.065296, 0.559039, 1.732407, 2.446417, 2.226664, 1.043498,
   -0.892194, 0.53867, 1.696599, 2.895421, 1.936742, 0.857415,
   1.777173, 1.489486, 0.990452, -0.312611, -2.485575, 5.784152,
   0.691233, 1.003065, 0.74676, 0.973191, 0.868018, 0.821039,
   0.770604, 1.139881, 1.057454, 1.00439, 0.595049, 0.733458,
   0.17767, -0.170966, -0.443584, -0.34547, 0.135814, -0.010206,
   0.585687, 1.040471, 0.778059, 0.994592, 0.882501, 0.81993,
   0.783313, 1.225092, 1.138965, 1.112052, 0.667895, 0.725504,
   -0.042205, -0.470107, -0.758346, -0.356139, 0.477461, 0.159831,
   0.465873, 0.827723, 0.635881, 0.876557, 0.751904, 0.689548,
   0.624036, 0.943642, 0.844483, 0.793347, 0.439269, 0.710473,
   0.362673, 0.107347, -0.123129, -0.079149, 0.300953, 0.33311,
   36.878339, -34.157785, 13.570499, -9.445193, 5.906855, -2.631383,
   -3.46685, 1.387212, 1.16875, -1.25244, -4.167107, 7.462264,
   4.218665, -10.616881, 2.816792, -0.854816, 0.465124, 3.805423,
   17.371809, -10.758329, 4.288758, -3.3009, -1.387066, -0.545407,
   -0.627846, 0.359405, -0.910465, 1.672222, -1.087077, 1.71169,
   1.892743, 1.370835, -1.074922, -2.069598, 2.132245, 3.323435,
   3.192245, 0.722216, 0.595036, 2.562026, 4.118245, 2.533825,
   0.661547, -0.522384, -0.923482, -0.744284, -0.531758, -1.737114,
   -0.894963, 0.335197, 2.767129, 0.169424, -1.86823, 2.057215,
   0.408584, 0.730536, 0.549013, 0.810092, 0.687577, 0.62613,
   0.551439, 0.839836, 0.758454, 0.711269, 0.388133, 0.706349,
   0.491137, 0.305519, 0.119262, 0.059367, 0.280111, 0.432421,
   11.3829, -2.355699, 0.800231, -0.812782, -1.725548, 0.506914,
   3.685745, -1.57036, -0.67807, -1.385545, 0.665419, -2.403472,
   0.348713, 0.948801, 3.943966, 0.60901, -2.954932, 6.570737,
   1.09868, 0.457162, 0.047123, 0.314413, 0.270546, 0.271241,
   0.44434, 0.685449, 0.881795, 0.904727, 0.538997, 0.274688,
   -0.10726, -0.182735, -0.297917, -0.722563, -1.004438, 2.114029,
   0.625319, 1.073737, 0.794572, 1.012257, 0.909403, 0.851104,
   0.819041, 1.284499, 1.213157, 1.195116, 0.731964, 0.733472,
   -0.119051, -0.57439, -0.865588, -0.405175, 0.494158, 0.142718,
   0.44362, 0.790221, 0.60428, 0.852407, 0.728354, 0.666281,
   0.59699, 0.903026, 0.80912, 0.758782, 0.416953, 0.708992,
   0.41504, 0.186673, -0.028387, -0.027435, 0.289143, 0.376176,
   0.377669, 0.691528, 0.513124, 0.786421, 0.670892, 0.613345,
   0.538605, 0.819386, 0.749119, 0.706133, 0.394004, 0.723393,
   0.551766, 0.390955, 0.222564, 0.125193, 0.287931, 0.397175,
   0.390177, 0.704718, 0.524964, 0.793337, 0.673926, 0.614109,
   0.538623, 0.821537, 0.747044, 0.702102, 0.386249, 0.712341,
   0.526445, 0.357474, 0.183363, 0.099539, 0.282065, 0.431269
};

var W2[90] = {
   0.313367, 0.600233, 0.413307, 0.723853, 0.604417, 0.564724,
   0.494233, 0.776964, 0.7137, 0.689037, 0.403412, 0.74366,
   0.681661, 0.582135, 0.470205, 0.320594, 0.360557, 0.505358,
   0.207009, -0.600315, 0.292799, -0.486397, -0.698483, -0.466675,
   0.16168, 1.267072, 0.942115, 1.601429, 0.294829, 2.066898,
   1.149577, -0.608109, 0.236174, 0.223691, 0.281142, 2.639872,
   0.298441, 0.585156, 0.397331, 0.714002, 0.591642, 0.547087,
   0.477829, 0.768086, 0.709662, 0.679375, 0.387499, 0.736123,
   0.665259, 0.56451, 0.453956, 0.305558, 0.345016, 0.50831,
   -0.677255, -1.032676, -0.744642, -0.925155, -1.197128, -0.992372,
   -0.855172, 7.016197, 5.226784, 2.411577, -0.733721, 3.402664,
   1.729731, -0.991801, -0.815011, -0.677321, -0.693829, 9.138765,
   -0.24649, -0.391846, -0.34772, -1.096698, -0.001496, -0.693606,
   -0.468658, 6.178259, 4.306803, 2.40946, -0.336563, 2.374341,
   1.504236, -0.726152, -0.426187, -0.25484, -0.293797, -1.89273
};

var W3[6] = {
   -0.62616, 1.717378, -0.485501, 2.751261, 2.323994, 2.047616
};

// ----------------------------- Neural network --------------------------------
var Sigmoid(var x)
{
   var ex;

   // Algebraically equivalent to the original tanh-like expression followed
   // by (x+1)/2, but numerically safer for large magnitudes.
   if(x > 40.0) return 0.999999999;
   if(x < -40.0) return 0.000000001;

   ex = pow(2.7182818,x);
   return ex/(1.0 + ex);
}

var ApplyNN(vars EmaSeries, int StartOffset)
{
   var H1[17];
   var H2[5];
   var sum;
   int neuron;
   int input;
   int k;

   // Layer 1: 17 inputs -> 17 hidden neurons.
   // Each neuron owns 17 weights followed by one bias. The MQL code SUBTRACTS
   // the stored bias, so we preserve sum(weights*inputs) - bias.
   k = 0;
   for(neuron = 0; neuron < 17; neuron++) {
      sum = 0.0;
      for(input = 0; input < 17; input++) {
         sum += W1[k] * EmaSeries[StartOffset + input];
         k++;
      }
      sum -= W1[k];
      k++;
      H1[neuron] = Sigmoid(sum);
   }

   // Layer 2: 17 -> 5.
   k = 0;
   for(neuron = 0; neuron < 5; neuron++) {
      sum = 0.0;
      for(input = 0; input < 17; input++) {
         sum += W2[k] * H1[input];
         k++;
      }
      sum -= W2[k];
      k++;
      H2[neuron] = Sigmoid(sum);
   }

   // Output layer: 5 -> 1.
   sum = 0.0;
   for(input = 0; input < 5; input++)
      sum += W3[input] * H2[input];
   sum -= W3[5];

   return 100.0 * Sigmoid(sum);
}

// ----------------------------- Indicator front-end ----------------------------
var NocValue()
{
   var Highest = priceH(0);
   var Lowest = priceL(0);
   var CloseNow = priceC(0);
   var Range;
   int i;

   for(i = 1; i < NocPeriod; i++) {
      if(priceH(i) > Highest) Highest = priceH(i);
      if(priceL(i) < Lowest) Lowest = priceL(i);
   }

   Range = Highest - Lowest;

   // Exact MQL4 expression, not a simplified approximation. When Range is
   // below 0.012, the denominator remains fixed at 0.012 and the value is
   // compressed around 0.5.
   if(Range > NocMinRange)
      return (CloseNow - Lowest - (Highest - CloseNow)) / Range / 2.0 + 0.5;
   else
      return (CloseNow - Lowest - (Highest - CloseNow)) / NocMinRange / 2.0 + 0.5;
}

// ----------------------------- Calendar mapping -------------------------------
int MQLDayToZorro(int MqlDay)
{
   // MQL4: Sunday=0. Zorro: Monday=1 ... Sunday=7.
   if(MqlDay == 0) return 7;
   return MqlDay;
}

int TradeAllowedToday()
{
   int d = dow(0);
   if(d == MQLDayToZorro(NoTradeDay_1)) return 0;
   if(d == MQLDayToZorro(NoTradeDay_2)) return 0;
   return 1;
}

// ----------------------------- Position sizing --------------------------------
var LotsOptimizedAmount()
{
   var amount;
   var freeMargin;
   var step;

   if(!UseMM)
      return FixedAmount;

   // Closest Zorro analogue of AccountFreeMargin().
   freeMargin = Equity - MarginVal;
   if(freeMargin < 0.0) freeMargin = 0.0;

   // Original MQL4 formula:
   // AccountFreeMargin() * Risk / 100 / 1000
   amount = freeMargin * RiskPercent / 100.0 / 1000.0;

   if(MiniAcct) {
      step = 0.01;
      amount = roundto(amount,step);
      if(amount < 0.01) amount = 0.01;
   } else {
      step = 0.1;
      amount = roundto(amount,step);
      if(amount < 0.1) amount = 0.1;
   }

   if(amount > 50.0) amount = 50.0;
   return amount;
}

// ----------------------------- Exact trailing ---------------------------------
int BogieTrailTMF(var TrailPips, var GuardPips)
{
   var distance;
   var guard;
   var candidate;

   if(!TradeIsOpen) return 0;
   if(TrailPips <= 0.0) return 0;

   distance = TrailPips * PIP;
   guard = GuardPips * PIP;

   if(TradeIsShort) {
      // Original SELL rule:
      // if(OrderStopLoss() > Ask + TrailingStop + 5*Point)
      //    SL = Ask + TrailingStop;
      candidate = priceC(0) + distance;
      if(TradeStopLimit > candidate + guard)
         TradeStopLimit = candidate;
   } else {
      // Zorro stop limits are expressed on the ask-price scale; this preserves
      // the original Bid-relative long trailing distance after spread handling.
      candidate = priceC(0) - distance;
      if(TradeStopLimit < candidate - guard)
         TradeStopLimit = candidate;
   }

   return 0;
}

// ------------------------------- Strategy -------------------------------------
function run()
{
   vars NocSeries;
   vars EmaSeries;
   var NocNow;
   var EmaNow;
   var NN_Shift1;
   var NN_Shift2;
   var TradeAmount;
   int BuySignal;
   int SellSignal;
   int Allowed;

   set(TICKS);              // TMF executes on incoming ticks/quotes.
   BarPeriod = 60;          // Original iCustom() signal timeframe: PERIOD_H1.
   LookBack = 250;          // >= original 200-bar warmup + NN/EMA history.
   Capital = 10000;

   asset(BogieAsset);
   algo("BogieNNv8");

   Hedge = 0;
   MaxLong = 1;
   MaxShort = 1;

   // Create the normalized oscillator and its EMA every bar. Series calls stay
   // unconditional, as required by Zorro.
   NocNow = NocValue();
   NocSeries = series(NocNow,64);
   EmaNow = EMA(NocSeries,EmaPeriod);
   EmaSeries = series(EmaNow,64);

   // MQL4 EA reads indicator buffer 1 at shifts 1 and 2.
   // Indicator output at shift s uses EMA values s+2 ... s+18.
   // Therefore:
   //   shift 1 -> EmaSeries[3..19]
   //   shift 2 -> EmaSeries[4..20]
   NN_Shift1 = ApplyNN(EmaSeries,3);
   NN_Shift2 = ApplyNN(EmaSeries,4);

   BuySignal = (NN_Shift2 <= BuyTrigger) && (NN_Shift1 >= BuyTrigger);
   SellSignal = (NN_Shift2 >= SellTrigger) && (NN_Shift1 <= SellTrigger);

   plot("BogieNN",NN_Shift1,NEW,RED);
   plot("Buy54",BuyTrigger,0,BLACK);
   plot("Sell74",SellTrigger,0,BLACK);

   if(is(LOOKBACK)) return;

   Allowed = TradeAllowedToday();

   // Preserve the original exit asymmetry exactly:
   // BUY closes on SELL signal OR no-trade day.
   if(NumOpenLong > 0) {
      if(SellSignal || !Allowed)
         exitLong();
   }

   // SELL closes only on BUY signal; no-trade-day alone does not close it.
   if(NumOpenShort > 0) {
      if(BuySignal)
         exitShort();
   }

   // No new entries on forbidden days.
   if(!Allowed) return;

   // Original EA allows only one symbol+magic position at once.
   if(NumOpenLong == 0 && NumOpenShort == 0) {
      TradeAmount = LotsOptimizedAmount();
      Amount = TradeAmount;

      // Disable Zorro's risk-based sizing; Amount reproduces MT4-lot sizing.
      Risk = 0;

      if(StopLossPips > 0.0) Stop = StopLossPips * PIP;
      else Stop = 0;

      if(TakeProfitPips > 0.0) TakeProfit = TakeProfitPips * PIP;
      else TakeProfit = 0;

      // Built-in Zorro Trail has different semantics from the MT4 EA.
      Trail = 0;

      if(BuySignal)
         enterLong(BogieTrailTMF,TrailingStopPips,TrailGuardPips);
      else if(SellSignal)
         enterShort(BogieTrailTMF,TrailingStopPips,TrailGuardPips);
   }
}