Re: Fix: Indicator is not showing on MT4 chart
Posted: Thu Sep 05, 2024 6:54 pm
Works fine.bluebird wrote: Tue Sep 03, 2024 10:57 pm Hey, Can this indicator be updated please? Much appreciated![]()
Works fine.bluebird wrote: Tue Sep 03, 2024 10:57 pm Hey, Can this indicator be updated please? Much appreciated![]()
When attached to the chart, it doesn't update/refresh automatically in real time. There is an error within the code that I struggle to fix myself. My coding abilities is limited compared to your expertise, please help
Code: Select all
#property indicator_separate_window
#property indicator_buffers 3
#property indicator_plots 3
//--- Plots
#property indicator_label1 "Volatility RSI"
#property indicator_type1 DRAW_LINE
#property indicator_color1 clrOrange
#property indicator_width1 2
#property indicator_label2 "Line 30"
#property indicator_type2 DRAW_LINE
#property indicator_color2 clrOrange
#property indicator_width2 1
#property indicator_style2 STYLE_DOT
#property indicator_label3 "Line 4"
#property indicator_type3 DRAW_LINE
#property indicator_color3 clrSaddleBrown
#property indicator_width3 1
#property indicator_style3 STYLE_DOT
//--- Inputs
extern int VolatilityLength = 8;
//--- Buffers
double VolatilityRSIBuffer[];
double HorizontalLine30[];
double HorizontalLine4[];
// -------------- Utilities & Math --------------
double Ln(double x)
{
// MQL4 does not have a built-in natural log named ln(),
// but it does have MathLog() which is ln(x).
return(MathLog(x));
}
// RMA (Wilder’s Smoothing) helper
// Equivalent to TradingView's ta.rma() if you do it in a rolling fashion.
// But we must do a "manual" approach using a loop.
double WilderRMA(double currentValue, double prevRma, int length)
{
// RMA = (prevRma*(length-1) + currentValue) / length
return((prevRma*(length-1) + currentValue) / length);
}
// -------------- Pine Script Functions Rewritten --------------
// _pv(_src, _len) = sqrt((_src / ((_len * 4) * ln(2))) * sum( (ln(high/low))^2, _len ))
double PVCalculation(int pos, int len)
{
// pos is the current bar index from left to right in MQL4
// _src = hlc3 = (High+Low+Close)/3 for the *current* bar
// we must sum over the last "len" bars for (ln(high/low))^2
// Here we do a standard loop for i in [pos..pos+len-1], carefully checking bounds.
if(pos + len >= Bars) return(0); // not enough bars to the left
double src = (High[pos] + Low[pos] + Close[pos]) / 3.0;
double sumLnSq = 0.0;
for(int i=0; i<len; i++)
{
int barIndex = pos + i;
if(barIndex >= Bars) break;
double h = High[barIndex];
double l = Low[barIndex];
if(l <= 0 || h <= 0) continue;
double val = Ln(h/l);
sumLnSq += val*val;
}
double denominator = (len * 4.0) * Ln(2.0); // (_len*4)*ln(2)
if(denominator == 0) return(0);
double result = 0.0;
// result = sqrt( (src / denominator) * sumLnSq )
result = MathSqrt((src / denominator) * sumLnSq);
return(result);
}
// _rsi(_src, _len)
// u = max(_src - _src[1], 0)
// d = max(_src[1] - _src, 0)
// rs = rma(u,_len)/rma(d,_len)
// res = 100 - 100/(1+rs)
double RSIOfSeries(double priceArray[], int pos, int len, int arraySize)
{
// We compute a short RSI over 'len' bars.
// MQL4 has iRSI, but we replicate Pine’s approach:
// We need a rolling calculation of U and D, then Wilder RMA of them.
if(len <= 0) return(0);
if(pos + len >= arraySize) return(0);
// Build arrays for U and D over the chunk
double rmaU = 0, rmaD = 0;
double prevRmaU = 0, prevRmaD = 0;
bool firstCalc = true;
// We go from oldest to newest: bar pos+len-1 up to pos
// so that the last step is "pos" (the current bar).
for(int i=len; i>0; i--)
{
int currentBar = pos + (i-1);
int previousBar = currentBar+1; // next to the right in MQL4 array
if(previousBar >= arraySize) continue;
double u = MathMax(priceArray[currentBar] - priceArray[previousBar], 0);
double d = MathMax(priceArray[previousBar] - priceArray[currentBar], 0);
if(firstCalc)
{
// initialize
prevRmaU = u;
prevRmaD = d;
firstCalc = false;
}
else
{
// update
prevRmaU = WilderRMA(u, prevRmaU, len);
prevRmaD = WilderRMA(d, prevRmaD, len);
}
}
// after finishing the loop, the last prevRmaU and prevRmaD are the final
// for the bar 'pos'
if(prevRmaD == 0) return(100.0); // avoid div-by-zero
double rs = prevRmaU / prevRmaD;
double rsi = 100.0 - (100.0 / (1.0 + rs));
return(rsi);
}
// Simple Harmonic function _simple_harmonic(_src, _len)
// Implementation note: We have to interpret c0= _src[pos], c1= _src[pos+1], c2= _src[pos+2], etc.
double SimpleHarmonic(double priceArray[], int pos, int len, int arraySize)
{
if(pos+2 >= arraySize) return(0);
double c0 = priceArray[pos];
double c1 = priceArray[pos+1];
double c2 = priceArray[pos+2];
double v0 = c0 - c1;
double v1 = c1 - c2;
double a0 = v0 - v1;
// We then take an EMA of a0 over length => a1
// For simplicity, we'll do a naive rolling approach again from pos+2 down to pos
// but since a0 is just 1 value (?), we’ll treat this with caution.
// In the original Pine, a0 is a series (bar by bar). This is more advanced.
// We'll approximate by just using the single a0’s WilderRMA for now:
// (Alternatively, you might store a separate buffer for a0 each bar.)
double a1 = a0; // or some smoothing if you want
// t0 = 2 * pi * sqrt( abs(v0 / a1) )
double pi = 3.14159265359;
double denominator = a1;
if(denominator == 0) denominator = 1e-9;
double t0 = 2.0 * pi * MathSqrt(MathAbs(v0/denominator));
// t1 = c0 > c1 ? t0 : -t0
double t1 = (c0 > c1)? t0 : -t0;
// In Pine, v3 = ema(t1, len) and t3 = ema(t0, len). We need bar-by-bar.
// For demonstration, we’ll just return the final SHO = (v3 / t3)*100
// by approximating v3 ~ t1 and t3 ~ t0. A more faithful port
// requires storing the entire t1, t0 series in arrays & applying EMA across bars.
// This is a big difference between Pine’s approach vs. MQL4 single-pass approach.
double v3 = t1;
double t3 = t0;
if(t3 == 0) return(0);
double sho = (v3/t3)*100.0;
return(sho);
}
// _karo(_src, _len)
// This is also a multi-bar logic in Pine that uses EMA. We simplify similarly.
double Karo(double priceArray[], int pos, int len, int arraySize)
{
// src = ema(_src, _len)
// Then some ratio-based logic.
// Here we do single-step for the current bar only (since a full port
// needs storing time series).
// We’ll approximate by using normal average of last 'len' bars:
if(pos + len >= arraySize) return(0);
double sum = 0;
for(int i=0; i<len; i++)
{
sum += priceArray[pos + i];
}
double src = sum / len; // approximate the "ema" with an "sma" for example
// a = ema(src < src[1] ? src/src[1] : 0, _len)
// b = ...
// The original code references src[1]. That means the bar to the right in MQL4 indexing.
// We'll just do a single-step approximation.
double src1 = (pos+1 < arraySize) ? priceArray[pos+1] : src;
double ratioCurrent = 0;
if(src1 != 0.0 && src < src1) ratioCurrent = src/src1;
double ratioOpposite = 0;
if(src1 != 0.0 && src > src1) ratioOpposite = src/src1;
// c = (src/src[1]) / ((src/src[1]) + b)
// d = 2 * ((src/src[1]) / ((src/src[1]) + c*a)) - 1
// We’ll approximate:
double cDen = ratioCurrent + ratioOpposite;
if(cDen == 0) cDen = 1e-9;
double cVal = ratioCurrent / cDen;
double karoden = ratioCurrent + cVal*ratioCurrent;
if(karoden == 0) karoden = 1e-9;
double dVal = 2.0 * (ratioCurrent / karoden) - 1.0;
return(dVal);
}
// _moscillator(_src, _len)
// Loops from 1 to _len
// if s0 > si => +1, if s0 < si => -1, else 0, sum them up
double MOscillator(double priceArray[], int pos, int len, int arraySize)
{
// s0 = _src[pos], si = _src[pos+i]
// sum up +1 / -1
if(pos + len >= arraySize) return(0);
double s0 = priceArray[pos];
int sum = 0;
for(int i=1; i<=len; i++)
{
int index = pos + i;
if(index >= arraySize) break;
double si = priceArray[index];
if(s0 > si) sum += 1;
else if(s0 < si) sum -= 1;
}
return(sum);
}
// typ7(_typ, _src, _len)
// In your Pine, you allowed multiple modes, but in your final code you used rsi_type.
// We replicate only the “RSI” path (since your variable `typ5 = rsi_type`).
// If you want to expand to “no_type, simp_harmon_type, karo_type, m_type”, add more logic.
double Typ7RSIOnly(double currentPV, int pos, int len, int arraySize, double priceArray[])
{
// We'll just do the RSI path from your code:
// _typ1 == rsi_type ? _rsi(_pv(...),_len) : ...
// Because you set typ5 = rsi_type in the final script.
// So effectively: volatility_rsi = _rsi( _pv(src0,VolatilityLength), VolatilityLength ).
// We pass in "currentPV" which is _pv(...) for the current bar.
// Now we build a small array so we can feed RSIOfSeries().
// But that requires a time series. We'll create a synthetic array with currentPV repeated,
// which doesn’t help RSI. Real port would store PV for each bar.
// The correct approach is: for each bar, compute PV, store it in an array, then feed that array to RSIOfSeries for the current bar.
return(currentPV); // <--- Stub if you only want the raw _pv()
// If you want the RSI of that PV time series, do the following:
// 1) Build an array that holds PV for all bars.
// 2) Then pass that array to RSIOfSeries(...).
// This example code, for simplicity, just returns the raw PV.
}
//--------------------------------------------
// OnInit
//--------------------------------------------
int OnInit()
{
// 3 buffers
SetIndexStyle(0, DRAW_LINE, EMPTY, 2, clrOrange);
SetIndexBuffer(0, VolatilityRSIBuffer);
SetIndexStyle(1, DRAW_LINE, STYLE_DOT, 1, clrOrange);
SetIndexBuffer(1, HorizontalLine30);
SetIndexStyle(2, DRAW_LINE, STYLE_DOT, 1, clrSaddleBrown);
SetIndexBuffer(2, HorizontalLine4);
IndicatorShortName("Breakout Detector (Converted from PineScript)");
return(INIT_SUCCEEDED);
}
//--------------------------------------------
// OnCalculate
//--------------------------------------------
// typical signature for MQL4:
// OnCalculate(int rates_total, int prev_calculated,
// const double &price[], ... )
// but we’ll just do a simplified version:
int OnCalculate(const int rates_total,
const int prev_calculated,
const int begin,
const double &price[])
{
// We want to fill VolatilityRSIBuffer for each bar.
// In Pine: volatility_rsi = _rsi( _pv(hlc3,VolatilityLength), VolatilityLength )
// We'll do the best we can in MQL4 with a single pass.
// Build an array for storing PV on each bar so we can then do RSI if desired
// For simplicity, let’s just store the PV and not do RSI on it (since that is more advanced).
// You can expand to do full RSI if needed.
static double PVArray[1]; // dynamic approach below
ArrayResize(PVArray, rates_total);
// prepare to read High[], Low[], Close[]; in MQL4 these are global arrays
// Make sure we handle indexing carefully: bar i in MQL4 = i-th from the left in OnCalculate loops.
// We'll fill from oldest bar to newest bar: i = 0..rates_total-1
// but watch out for access High[i], Low[i], etc. in the same direction.
int limit = rates_total - prev_calculated;
if(limit > rates_total) limit = rates_total;
for(int i=0; i<limit; i++)
{
// compute PV for bar i
double pvVal = PVCalculation(i, VolatilityLength);
PVArray[i] = pvVal; // store it so we can do RSI, etc.
// If you want RSI of PV, you’d do something like:
// double rsiVal = RSIOfSeries(PVArray, i, VolatilityLength, rates_total);
// VolatilityRSIBuffer[i] = rsiVal;
// Here we just do the stub for demonstration:
VolatilityRSIBuffer[i] = pvVal;
// Set the lines
HorizontalLine30[i] = 30.0;
HorizontalLine4[i] = 4.0;
}
//-------------------------
// Emulate alertcondition(ta.crossunder(volatility_rsi,15))
// crossunder => volatility_rsi just went from >= 15 to < 15
// We can check the last bar processed:
if(rates_total > 1)
{
int iCur = limit - 1; // the most recent bar we processed
int iPrev = iCur + 1; // the bar to the right (previous in Pine sense)
if(iPrev < rates_total)
{
double curVal = VolatilityRSIBuffer[iCur];
double prevVal = VolatilityRSIBuffer[iPrev];
if(curVal < 15.0 && prevVal >= 15.0)
{
Alert("Breakout Zone: crossunder 15 detected on bar ", iCur);
}
}
}
//-------------------------
return(rates_total);
}
Code: Select all
for(int i=0; i<limit; i++)
{
double pvVal = PVCalculation(i, VolatilityLength);
...
VolatilityRSIBuffer[i] = pvVal;
}
Code: Select all
// pos is the current bar index from left to right in MQL4
// ...
if(pos + len >= Bars) return(0);
Code: Select all
int limit = rates_total - prev_calculated;
if(limit > rates_total) limit = rates_total;
for(int i = rates_total - 1; i >= 0; i--)
{
double pvVal = PVCalculation(i, VolatilityLength);
VolatilityRSIBuffer[i] = pvVal;
HorizontalLine30[i] = 30.0;
HorizontalLine4[i] = 4.0;
}
Code: Select all
if(pos + len >= Bars) return(0); // not enough bars to the left
Code: Select all
// If we want to ensure that "pos + (len - 1)" does not exceed the oldest bar index:
if(pos + (len - 1) > (Bars - 1))
return(0);
Code: Select all
// If 'pos' is the oldest bar index, and we need the next 'len' bars to the right:
if(pos - (len - 1) < 0)
return(0);
Code: Select all
for(int i=rates_total-1; i>=0; i--)
{
double pvVal = PVCalculation(i, VolatilityLength);
Print("Bar=", i, " PV=", pvVal);
VolatilityRSIBuffer[i] = pvVal;
...
}
Code: Select all
#property indicator_separate_window
#property indicator_label1 "Volatility RSI"
#property indicator_type1 DRAW_LINE
#property indicator_color1 clrOrange
#property indicator_width1 2
Code: Select all
int limit = rates_total - prev_calculated;
if(limit > rates_total) limit = rates_total;
for(int i=0; i<limit; i++)
{
...
}
Code: Select all
int start = prev_calculated;
if(start < 1) start = 0;
for(int i = start; i < rates_total; i++)
{
...
}
Code: Select all
for(int i = rates_total-1; i >= 0; i--)
{
...
}
Code: Select all
int OnCalculate(const int rates_total,
const int prev_calculated,
const int begin,
const double &price[])
{
int limit = rates_total - prev_calculated;
if(limit > rates_total) limit = rates_total;
// We'll process from the oldest bar to the newest bar:
// i = rates_total-1 (oldest) down to 0 (newest)
for(int i = rates_total - 1; i >= 0; i--)
{
double pvVal = PVCalculation(i, VolatilityLength);
VolatilityRSIBuffer[i] = pvVal;
HorizontalLine30[i] = 30.0;
HorizontalLine4[i] = 4.0;
}
return(rates_total);
}
Code: Select all
double PVCalculation(int pos, int len)
{
// If pos is an older bar index, pos+len might be an even older bar index
// But in MQL4, a bigger index = older bar. So you might want "pos - len" instead.
// Adjust your condition. For example:
if(pos - (len - 1) < 0) return(0); // means not enough older bars to do the sum
double src = (High[pos] + Low[pos] + Close[pos]) / 3.0;
double sumLnSq = 0.0;
for(int i=0; i<len; i++)
{
int barIndex = pos - i;
if(barIndex < 0) break;
double h = High[barIndex];
double l = Low[barIndex];
if(l <= 0.0 || h <= 0.0) continue;
double val = MathLog(h / l);
sumLnSq += val * val;
}
double denominator = (len * 4.0) * MathLog(2.0);
if(denominator == 0) return(0);
double result = MathSqrt((src / denominator) * sumLnSq);
return(result);
}
Could you please give me the name or link of the indicator in Tradeview?RACER-X wrote: Fri Dec 27, 2024 9:44 pm Hi all. I was trying to convert a PineScript indicator from Tradingview over to MQL4 for MT4.
I used ChatGPT Pro to do it. And the finished code compiled with no errors.
But the indicator shows up blank on the chart.
Can you help me fix it?
Here is the mql4 code:
Code: Select all
#property indicator_separate_window #property indicator_buffers 3 #property indicator_plots 3 //--- Plots #property indicator_label1 "Volatility RSI" #property indicator_type1 DRAW_LINE #property indicator_color1 clrOrange #property indicator_width1 2 #property indicator_label2 "Line 30" #property indicator_type2 DRAW_LINE #property indicator_color2 clrOrange #property indicator_width2 1 #property indicator_style2 STYLE_DOT #property indicator_label3 "Line 4" #property indicator_type3 DRAW_LINE #property indicator_color3 clrSaddleBrown #property indicator_width3 1 #property indicator_style3 STYLE_DOT //--- Inputs extern int VolatilityLength = 8; //--- Buffers double VolatilityRSIBuffer[]; double HorizontalLine30[]; double HorizontalLine4[]; // -------------- Utilities & Math -------------- double Ln(double x) { // MQL4 does not have a built-in natural log named ln(), // but it does have MathLog() which is ln(x). return(MathLog(x)); } // RMA (Wilder’s Smoothing) helper // Equivalent to TradingView's ta.rma() if you do it in a rolling fashion. // But we must do a "manual" approach using a loop. double WilderRMA(double currentValue, double prevRma, int length) { // RMA = (prevRma*(length-1) + currentValue) / length return((prevRma*(length-1) + currentValue) / length); } // -------------- Pine Script Functions Rewritten -------------- // _pv(_src, _len) = sqrt((_src / ((_len * 4) * ln(2))) * sum( (ln(high/low))^2, _len )) double PVCalculation(int pos, int len) { // pos is the current bar index from left to right in MQL4 // _src = hlc3 = (High+Low+Close)/3 for the *current* bar // we must sum over the last "len" bars for (ln(high/low))^2 // Here we do a standard loop for i in [pos..pos+len-1], carefully checking bounds. if(pos + len >= Bars) return(0); // not enough bars to the left double src = (High[pos] + Low[pos] + Close[pos]) / 3.0; double sumLnSq = 0.0; for(int i=0; i<len; i++) { int barIndex = pos + i; if(barIndex >= Bars) break; double h = High[barIndex]; double l = Low[barIndex]; if(l <= 0 || h <= 0) continue; double val = Ln(h/l); sumLnSq += val*val; } double denominator = (len * 4.0) * Ln(2.0); // (_len*4)*ln(2) if(denominator == 0) return(0); double result = 0.0; // result = sqrt( (src / denominator) * sumLnSq ) result = MathSqrt((src / denominator) * sumLnSq); return(result); } // _rsi(_src, _len) // u = max(_src - _src[1], 0) // d = max(_src[1] - _src, 0) // rs = rma(u,_len)/rma(d,_len) // res = 100 - 100/(1+rs) double RSIOfSeries(double priceArray[], int pos, int len, int arraySize) { // We compute a short RSI over 'len' bars. // MQL4 has iRSI, but we replicate Pine’s approach: // We need a rolling calculation of U and D, then Wilder RMA of them. if(len <= 0) return(0); if(pos + len >= arraySize) return(0); // Build arrays for U and D over the chunk double rmaU = 0, rmaD = 0; double prevRmaU = 0, prevRmaD = 0; bool firstCalc = true; // We go from oldest to newest: bar pos+len-1 up to pos // so that the last step is "pos" (the current bar). for(int i=len; i>0; i--) { int currentBar = pos + (i-1); int previousBar = currentBar+1; // next to the right in MQL4 array if(previousBar >= arraySize) continue; double u = MathMax(priceArray[currentBar] - priceArray[previousBar], 0); double d = MathMax(priceArray[previousBar] - priceArray[currentBar], 0); if(firstCalc) { // initialize prevRmaU = u; prevRmaD = d; firstCalc = false; } else { // update prevRmaU = WilderRMA(u, prevRmaU, len); prevRmaD = WilderRMA(d, prevRmaD, len); } } // after finishing the loop, the last prevRmaU and prevRmaD are the final // for the bar 'pos' if(prevRmaD == 0) return(100.0); // avoid div-by-zero double rs = prevRmaU / prevRmaD; double rsi = 100.0 - (100.0 / (1.0 + rs)); return(rsi); } // Simple Harmonic function _simple_harmonic(_src, _len) // Implementation note: We have to interpret c0= _src[pos], c1= _src[pos+1], c2= _src[pos+2], etc. double SimpleHarmonic(double priceArray[], int pos, int len, int arraySize) { if(pos+2 >= arraySize) return(0); double c0 = priceArray[pos]; double c1 = priceArray[pos+1]; double c2 = priceArray[pos+2]; double v0 = c0 - c1; double v1 = c1 - c2; double a0 = v0 - v1; // We then take an EMA of a0 over length => a1 // For simplicity, we'll do a naive rolling approach again from pos+2 down to pos // but since a0 is just 1 value (?), we’ll treat this with caution. // In the original Pine, a0 is a series (bar by bar). This is more advanced. // We'll approximate by just using the single a0’s WilderRMA for now: // (Alternatively, you might store a separate buffer for a0 each bar.) double a1 = a0; // or some smoothing if you want // t0 = 2 * pi * sqrt( abs(v0 / a1) ) double pi = 3.14159265359; double denominator = a1; if(denominator == 0) denominator = 1e-9; double t0 = 2.0 * pi * MathSqrt(MathAbs(v0/denominator)); // t1 = c0 > c1 ? t0 : -t0 double t1 = (c0 > c1)? t0 : -t0; // In Pine, v3 = ema(t1, len) and t3 = ema(t0, len). We need bar-by-bar. // For demonstration, we’ll just return the final SHO = (v3 / t3)*100 // by approximating v3 ~ t1 and t3 ~ t0. A more faithful port // requires storing the entire t1, t0 series in arrays & applying EMA across bars. // This is a big difference between Pine’s approach vs. MQL4 single-pass approach. double v3 = t1; double t3 = t0; if(t3 == 0) return(0); double sho = (v3/t3)*100.0; return(sho); } // _karo(_src, _len) // This is also a multi-bar logic in Pine that uses EMA. We simplify similarly. double Karo(double priceArray[], int pos, int len, int arraySize) { // src = ema(_src, _len) // Then some ratio-based logic. // Here we do single-step for the current bar only (since a full port // needs storing time series). // We’ll approximate by using normal average of last 'len' bars: if(pos + len >= arraySize) return(0); double sum = 0; for(int i=0; i<len; i++) { sum += priceArray[pos + i]; } double src = sum / len; // approximate the "ema" with an "sma" for example // a = ema(src < src[1] ? src/src[1] : 0, _len) // b = ... // The original code references src[1]. That means the bar to the right in MQL4 indexing. // We'll just do a single-step approximation. double src1 = (pos+1 < arraySize) ? priceArray[pos+1] : src; double ratioCurrent = 0; if(src1 != 0.0 && src < src1) ratioCurrent = src/src1; double ratioOpposite = 0; if(src1 != 0.0 && src > src1) ratioOpposite = src/src1; // c = (src/src[1]) / ((src/src[1]) + b) // d = 2 * ((src/src[1]) / ((src/src[1]) + c*a)) - 1 // We’ll approximate: double cDen = ratioCurrent + ratioOpposite; if(cDen == 0) cDen = 1e-9; double cVal = ratioCurrent / cDen; double karoden = ratioCurrent + cVal*ratioCurrent; if(karoden == 0) karoden = 1e-9; double dVal = 2.0 * (ratioCurrent / karoden) - 1.0; return(dVal); } // _moscillator(_src, _len) // Loops from 1 to _len // if s0 > si => +1, if s0 < si => -1, else 0, sum them up double MOscillator(double priceArray[], int pos, int len, int arraySize) { // s0 = _src[pos], si = _src[pos+i] // sum up +1 / -1 if(pos + len >= arraySize) return(0); double s0 = priceArray[pos]; int sum = 0; for(int i=1; i<=len; i++) { int index = pos + i; if(index >= arraySize) break; double si = priceArray[index]; if(s0 > si) sum += 1; else if(s0 < si) sum -= 1; } return(sum); } // typ7(_typ, _src, _len) // In your Pine, you allowed multiple modes, but in your final code you used rsi_type. // We replicate only the “RSI” path (since your variable `typ5 = rsi_type`). // If you want to expand to “no_type, simp_harmon_type, karo_type, m_type”, add more logic. double Typ7RSIOnly(double currentPV, int pos, int len, int arraySize, double priceArray[]) { // We'll just do the RSI path from your code: // _typ1 == rsi_type ? _rsi(_pv(...),_len) : ... // Because you set typ5 = rsi_type in the final script. // So effectively: volatility_rsi = _rsi( _pv(src0,VolatilityLength), VolatilityLength ). // We pass in "currentPV" which is _pv(...) for the current bar. // Now we build a small array so we can feed RSIOfSeries(). // But that requires a time series. We'll create a synthetic array with currentPV repeated, // which doesn’t help RSI. Real port would store PV for each bar. // The correct approach is: for each bar, compute PV, store it in an array, then feed that array to RSIOfSeries for the current bar. return(currentPV); // <--- Stub if you only want the raw _pv() // If you want the RSI of that PV time series, do the following: // 1) Build an array that holds PV for all bars. // 2) Then pass that array to RSIOfSeries(...). // This example code, for simplicity, just returns the raw PV. } //-------------------------------------------- // OnInit //-------------------------------------------- int OnInit() { // 3 buffers SetIndexStyle(0, DRAW_LINE, EMPTY, 2, clrOrange); SetIndexBuffer(0, VolatilityRSIBuffer); SetIndexStyle(1, DRAW_LINE, STYLE_DOT, 1, clrOrange); SetIndexBuffer(1, HorizontalLine30); SetIndexStyle(2, DRAW_LINE, STYLE_DOT, 1, clrSaddleBrown); SetIndexBuffer(2, HorizontalLine4); IndicatorShortName("Breakout Detector (Converted from PineScript)"); return(INIT_SUCCEEDED); } //-------------------------------------------- // OnCalculate //-------------------------------------------- // typical signature for MQL4: // OnCalculate(int rates_total, int prev_calculated, // const double &price[], ... ) // but we’ll just do a simplified version: int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[]) { // We want to fill VolatilityRSIBuffer for each bar. // In Pine: volatility_rsi = _rsi( _pv(hlc3,VolatilityLength), VolatilityLength ) // We'll do the best we can in MQL4 with a single pass. // Build an array for storing PV on each bar so we can then do RSI if desired // For simplicity, let’s just store the PV and not do RSI on it (since that is more advanced). // You can expand to do full RSI if needed. static double PVArray[1]; // dynamic approach below ArrayResize(PVArray, rates_total); // prepare to read High[], Low[], Close[]; in MQL4 these are global arrays // Make sure we handle indexing carefully: bar i in MQL4 = i-th from the left in OnCalculate loops. // We'll fill from oldest bar to newest bar: i = 0..rates_total-1 // but watch out for access High[i], Low[i], etc. in the same direction. int limit = rates_total - prev_calculated; if(limit > rates_total) limit = rates_total; for(int i=0; i<limit; i++) { // compute PV for bar i double pvVal = PVCalculation(i, VolatilityLength); PVArray[i] = pvVal; // store it so we can do RSI, etc. // If you want RSI of PV, you’d do something like: // double rsiVal = RSIOfSeries(PVArray, i, VolatilityLength, rates_total); // VolatilityRSIBuffer[i] = rsiVal; // Here we just do the stub for demonstration: VolatilityRSIBuffer[i] = pvVal; // Set the lines HorizontalLine30[i] = 30.0; HorizontalLine4[i] = 4.0; } //------------------------- // Emulate alertcondition(ta.crossunder(volatility_rsi,15)) // crossunder => volatility_rsi just went from >= 15 to < 15 // We can check the last bar processed: if(rates_total > 1) { int iCur = limit - 1; // the most recent bar we processed int iPrev = iCur + 1; // the bar to the right (previous in Pine sense) if(iPrev < rates_total) { double curVal = VolatilityRSIBuffer[iCur]; double prevVal = VolatilityRSIBuffer[iPrev]; if(curVal < 15.0 && prevVal >= 15.0) { Alert("Breakout Zone: crossunder 15 detected on bar ", iCur); } } } //------------------------- return(rates_total); }
-------------------------------------------------------------------------------------------------------------------------------------------------
Attached is the indicator.
Here is some logic in the PineScript to MQL4 conversion is also attached.
I don't have the link. The name is Breakout Detector.mrtools wrote: Fri Dec 27, 2024 11:56 pm Could you please give me the name or link of the indicator in Tradeview?
Code: Select all
//@version=5
tag0 = "TC Breakout Detector"
indicator("Breakout Detector")
pi = 3.14159265359
src0 = hlc3
volatility_length = input(8,title="Volatility Length")
no_type = "Standard"
simp_harmon_type = "Simple Harmonic"
rsi_type = "RSI"
karo_type = "Karobein"
m_type = "M-Oscillator"
typ5 = rsi_type
_pv(_src, _len) =>
math.sqrt((_src / ((_len * 4) * math.log(2))) * math.sum(math.pow(math.log(high / low), 2), _len))
_rma(_src, _len) =>
ta.sma(_src, _len * 3) + ta.sma(_src, _len * 2) - ta.sma(_src, _len)
_rsi(_src, _len) =>
u = math.max(_src - _src[1], 0)
d = math.max(_src[1] - _src, 0)
rs = ta.rma(u, _len) / ta.rma(d, _len)
res = 100 - 100 / (1 + rs)
res
_simple_harmonic(_src, _len) =>
c0 = _src
c1 = c0[1]
c2 = c0[2]
v0 = c0 - c1
v1 = c1 - c2
a0 = v0 - v1
a1 = ta.ema(a0, _len)
t0 = 2 * pi * (math.sqrt(math.abs(v0 / a1)))
t1 = c0 > c1 ? t0 : t0 * -1
v3 = ta.ema(t1, _len)
t3 = ta.ema(t0, _len)
sho = (v3 / t3) * 100
_karo(_src, _len) =>
src = ta.ema(_src, _len)
a = ta.ema(src < src[1] ? src / src[1] : 0, _len)
b = ta.ema(src > src[1] ? src / src[1] : 0, _len)
c = (src / src[1]) / (src / src[1] + b)
d = 2 * ((src / src[1]) / (src / src[1] + c * a)) - 1
_moscillator(_src, _len) =>
tt_c = 0
for i = 1 to _len
s0 = _src[0]
si = _src[i]
t_c = s0 > si ? 1 :s0 < si ? -1 : 0
tt_c := tt_c + t_c
tt_c
tt_c
typ7(_typ1, _src, _len) =>
_typ1 == no_type ? _pv(src0, volatility_length) :
_typ1 == rsi_type ? _rsi(_pv(src0, volatility_length), _len) :
_typ1 == simp_harmon_type ? _simple_harmonic(_pv(src0, volatility_length), _len) :
_typ1 == karo_type ? _karo(_pv(src0, volatility_length), _len) :
_typ1 == m_type ? ta.ema(ta.ema(_moscillator(_pv(src0, volatility_length), _len), 5), 3) : na
cond0 = typ5
cond1 = cond0 == no_type ? src0 : _pv(src0, volatility_length)
cond2 = cond0 == no_type ? volatility_length : volatility_length
volatility_rsi = typ7(cond0, cond1, cond2)
plot(volatility_rsi, tag0, #f5ab0c, 1, style=plot.style_line,transp=5)
h1=hline(30, color=#f5ab0c21, linestyle=hline.style_solid, linewidth=2)
h2=hline(4, color=#806732, linestyle=hline.style_solid, linewidth=2)
fill(h1, h2, color = color.new(#ff9900, 85))
makelabel(x, y, msg, col=color.white)=>
var label _la = label.new(x, y, msg, color=#00000000, style=label.style_label_left)
label.set_xy(_la, x, y)
label.set_text(_la, msg)
label.set_textcolor(_la, col)
_la
bc = 16
makelabel(bar_index+10, bc, 'Breakout Zone ↑↓')
alertcondition(ta.crossunder(volatility_rsi,15), title='Breakout Zone', message='Breakout Zone')
That is an early interpolated version of Awesome (interpolation was called ratio) we have a lot of newer Awesome using interpolation mtf in the forum now.