Hello guys,
I’ve coded the cybernetic oscillator by John F. Ehlers, taking it from the article “Making a Better Oscillator” from the TASC journal, but I’ve faced some issues.
The original code is written in Easy Language, you can find it in the pdf attached. I wrote in the same page the code of the high-pass filter, the Super Smoother and the RMS formula to obtain the final formula of the cybernetic oscillator, without calling the other indicators from external codes.
The problem is that the oscillator’s values exploded in the first periods while are too small in the latests, so it seems like it’s not normalized as it should.
Can anyone help me? The following is the code written in ProRealTime:
// === Coefficienti High-Pass ===
a1HP = EXP(-(SQRT(2) * 3.14159) / HPLength)
b1HP = 2 * a1HP * COS((SQRT(2) * 180) / HPLength)
c2HP = b1HP
c3HP = -(a1HP * a1HP)
c1HP = (1 + c2HP - c3HP)/4
// === High-Pass Filter ===
IF BarIndex >= 4 THEN
HP = c1HP * (Close - 2*Close[1] + Close[2]) + c2HP * HP[1] + c3HP * HP[2]
ELSE
HP = 0
ENDIF
// === Coefficienti Super Smoother ===
a1SS = EXP(-(SQRT(2) * 3.14159) / LPLength)
b1SS = 2 * a1SS * COS((SQRT(2) * 180) / LPLength)
c2SS = b1SS
c3SS = -(a1SS * a1SS)
c1SS = 1 - c2SS - c3SS
// === Super Smoother ===
IF BarIndex >= 4 THEN
SS = c1SS * (HP + HP[1]) / 2 + c2SS * SS[1] + c3SS * SS[2]
ELSE
SS = HP
ENDIF
// === RMS ===
SumSq = 0
FOR Count = 0 to RMSLength - 1 DO
Sumsq = SumSq + SS[count]*SS[Count]
NEXT
IF SumSq <> 0 THEN
RMS = SQR(SumSq/RMSLength)
ENDIF
// === Cybernetic Oscillator ===
IF RMS <> 0 THEN
CyberneticOscillator = SS / RMS
ENDIF
RETURN CyberneticOscillator AS "Cybenrnetic Oscillator"
The variables HPLength, LPLength and RMSLength are set as parameters in the ProBuilder code editor.
I attached also a screenshot of the behaviour of the CO, applied to the graph of the NASDAQ Index.
The PDF file is missing, if you can’t attach it, please post the text of the code.
Hi! I found the oscillator in trading view.
// ====================================================
//PRC_Cybernetic Oscillator (John Ehlers, TASC 2025)
//version = 0
//01.10.25
//Iván González @ www.prorealcode.com
//Sharing ProRealTime knowledge
// ====================================================
// ----- Parámetros
hpPeriod = 30 // Periodo filtro Highpass
lpPeriod = 20 // Periodo filtro Lowpass (Super Smoother)
rmsLen = 100 // Longitud RMS
threshold = 1 // Umbral opcional
// ----- Constantes
pi = 3.1415926535
sqrt2 = 1.41421356237
src = close
// ====================================================
// Calculos
// ====================================================
if barindex>=4 then
// ----- High-Pass Filter (2nd order)
a0 = sqrt2 * pi / hpPeriod
a1 = EXP(-a0)
c2hp = 2*a1*COS(a0*180/pi)
c3hp = -(a1*a1)
c1hp = (1 + c2hp - c3hp) * 0.25
hp = 0
hp = c1hp * (src - 2*src[1] + src[2]) + c2hp*hp[1] + c3hp*hp[2]
// ----- Super Smoother (Low-Pass, 2nd order)
a0lp = sqrt2 * pi / lpPeriod
a1lp = EXP(-a0lp)
c2lp = 2*a1lp*COS(a0lp*180/pi)
c3lp = -(a1lp*a1lp)
c1lp = 1 - c2lp - c3lp
lp = 0
lp = c1lp * 0.5*(hp + hp[1]) + c2lp*lp[1] + c3lp*lp[2]
endif
// ====================================================
// RMS Normalization
// ====================================================
pow2 = lp*lp
rms = SQRT(Average[rmsLen](pow2))
epsilon = 0.000001
den = MAX(rms, epsilon)
osc = lp / den
// ====================================================
// Líneas de referencia
// ====================================================
zeroline = 0
upth = threshold
lowth = -threshold
if osc > 0 then
red=0
green=255
blue=0
else
red=255
green=0
blue=0
endif
// ====================================================
RETURN osc AS "Cybernetic Osc" coloured(red,green,blue)style(line,3),zeroline COLOURED(200,200,200) AS "0",upth COLOURED(150,150,150) AS "+Threshold",lowth COLOURED(150,150,150) AS "-Threshold"
Ops, sorry, It hasn’t been uploaded. I’ll try again, if it doesn’t work, here is the code, written in EasyLanguage from the original file:
High-Pass filter:
{
Highpass Function
(C) 2004-2024 John F. Ehlers
}
Inputs:
Price(numericseries),
Period(numericsimple);
Vars:
a1(0),
b1(0),
c1(0),
c2(0),
c3(0);
a1 = expvalue(-1.414*3.14159 / Period);
b1 = 2*a1*Cosine(1.414*180 / Period);
c2 = b1;
c3 = -a1*a1;
c1 = (1 + c2 – c3) / 4;
If CurrentBar >= 4 Then $HighPass = c1*(Price – 2*Price[1] +
Price[2]) + c2*$HighPass[1] + c3*$HighPass[2];
If Currentbar < 4 Then $HighPass = 0;
Super Smoother:
{
SuperSmoother Function
(C) 2004-2025 John F. Ehlers
}
Inputs:
Price(numericseries),
Period(numericsimple);
Vars:
a1(0),
b1(0),
c1(0),
c2(0),
c3(0);
a1 = expvalue(-1.414*3.14159 / Period);
b1 = 2*a1*Cosine(1.414*180 / Period);
c2 = b1;
c3 = -a1*a1;
c1 = 1 - c2 - c3;
If CurrentBar >= 4 Then $SuperSmoother =
c1*(Price + Price[1]) / 2 + c2*$SuperSmoother[1] +
c3*$SuperSmoother[2];
If Currentbar < 4 Then $SuperSmoother = Price;
Root Mean Square:
{
RMS Function
(C) 2015-2025 John F. Ehlers
}
Inputs:
Price(numericseries),
Length(numericsimple);
Vars:
SumSq(0),
count(0);
SumSq = 0;
for count = 0 to Length - 1 Begin
SumSq = SumSq + Price[count]*Price[count];
End;
If SumSq <> 0 Then $RMS = SquareRoot(SumSq / Length);
Final formula of the Cybernetic Oscillator:
{
Cybernetic Oscillator
(C) 2025 John F. Ehlers
}
Inputs:
HPLength(30),
LPLength(20);
Vars:
HP(0),
LP(0),
RMS(0),
CyberneticOsc(0);
HP = $HighPass(Close, HPLength);
LP = $SuperSmoother(HP, LPLength);
RMS = $RMS(LP, 100);
If RMS <> 0 Then CyberneticOsc = LP / RMS;
Plot1(CyberneticOsc);
Plot2(0);
Thanks!
I did wrong something about the RMS formula, I guess, now the values are way more stable and the same of the cybernetic oscillator posted on TradingView.