The Force Index (EFI), originally developed by Dr. Alexander Elder, is a classic oscillator that measures the power behind a price move. It combines the three essential elements of market action: the direction of the price change, the extent of the change, and the volume. A significant price move on high volume results in a high Force Index value, while a small move on low volume results in a low value.
This advanced version, enhances the original concept in two significant ways:
The “force” of each bar is calculated with the classic formula: (Current Close - Previous Close) * Volume. This raw value is then smoothed using an Exponential Moving Average (EMA) to create the main EFI line (blue). A second, typically slower, EMA is applied to the EFI line to create the Signal line (orange).
Here is the complete article for ProRealcode.com, written in English and formatted for easy publishing.
The Force Index (EFI), originally developed by Dr. Alexander Elder, is a classic oscillator that measures the power behind a price move. It combines the three essential elements of market action: the direction of the price change, the extent of the change, and the volume. A significant price move on high volume results in a high Force Index value, while a small move on low volume results in a low value.
This advanced version enhances the original concept in two significant ways:
The “force” of each bar is calculated with the classic formula: (Current Close - Previous Close) * Volume. This raw value is then smoothed using an Exponential Moving Average (EMA) to create the main EFI line (blue). A second, typically slower, EMA is applied to the EFI line to create the Signal line (orange).
This indicator gives you two choices for its calculation method, set by the calcType input:
calcType = 1): This is the default. The indicator behaves like a standard EFI, using the fixed periods you define in the settings (len for the EFI, slen for the Signal line) .calcType = 0): This mode activates a sophisticated band-pass filter to analyze price action and determine the current dominant market cycle. It then uses this detected cycle length to automatically adjust the periods for the EFI, Signal, and ATR calculations. This makes the indicator more responsive in fast, active markets and smoother during quiet consolidation.Instead of using the price’s ATR, this indicator cleverly calculates the volatility of the EFI line itself. It does this by taking an EMA of the absolute difference between consecutive EFI values.
It then plots three sets of these ATR bands (at 1x, 2x, and 3x the multiplier) around the orange Signal line. These channels function as dynamic “overbought” and “oversold” levels based on the EFI’s current volatility.
The truncAtr setting (on by default) helps to normalize the oscillator. If the EFI value tries to spike far beyond the 3rd ATR band, this feature will “cap” or “truncate” the visual plot at the 3rd band. This prevents a single extreme spike from skewing the chart and makes it easier to read.
atrHigh2 or atrHigh3), it signals a very strong, potentially over-extended, or “climactic” move.Here are the inputs you can customize in the indicator’s settings panel:
This is the master switch for the calculation method.
1 = Fixed Mode0 = Band-pass (Adaptive) Mode(These are only used if calcType is set to 1)
(These are only used if calcType is set to 0)
Controls the “capping” of the EFI line.
1 = Truncate (cap) the EFI line at the 3rd ATR band.0 = Do Not Truncate (allow the EFI line to draw its true value).//-----------------------------------------//
//PRC_Elder Force index
//version = 0
//18.09.2024
//Iván González @ www.prorealcode.com
//Sharing ProRealTime knowledge
//-----------------------------------------//
//-----Inputs------------------------------//
//-----------------------------------------//
src=close
calcType=1 //Boolean//1=Fixed 0=Band-pass Dominant Cycle
len=13 //Fixed EFI Period
slen=21 //Fixed Signal Period
atrM=21 //Fixed ATR Smoothing Length
bpPeriod=13 //Band-pass period
bpWidth=0.20 //Band-pass Width
cycleLen=100/100 //Signal and ATR percent of dominant cycle (%)
efireduction=75/100 //EFI percent of dominat cycle (%)
atrMult1=1
atrMult2=2
atrMult3=3
truncAtr=1 //truncate over ATR Mult Level 4?
//-----------------------------------------//
//--Length Out calculation Band-pass type--//
//-----------------------------------------//
peak=0
real=0
counter=0
dc=0
alpha2=(cos(0.25*bpWidth*2*180/bpPeriod)+sin(0.25*bpWidth*2*180/bpPeriod)-1)/cos(0.25*bpWidth*2*180/bpPeriod)
if barindex<=1 then
hp=0
else
hp=(1+alpha2/2)*(close-close[1])+(1-alpha2)*hp[1]
endif
beta1=cos(2*180/bpPeriod)
gamma1=1/cos(2*180*bpWidth/bpPeriod)
alpha1=gamma1-sqrt(gamma1*gamma1-1)
if barindex<=2 then
bp=0
else
bp=0.5*(1-alpha1)*(hp-hp[2])+beta1*(1+alpha1)*bp[1]-alpha1*bp[2]
endif
peak=0.991*peak
if abs(bp)>peak then
peak=abs(bp)
else
peak=peak
endif
if peak<>0 then
real=bp/peak
else
real=real
endif
if dc<6 then
dc=6
else
dc=dc
endif
counter=counter+1
if real crosses over 0 or real crosses under 0 then
dc=2*counter
if 2*counter>1.25*dc[1] then
dc=1.25*dc[1]
elsif 2*counter<0.8*dc[1] then
dc=0.8*dc[1]
endif
counter=0
endif
tempoutFast=efireduction*dc
tempoutSlow=cycleLen*dc
if tempoutFast<1 then
lenOutFast=1
else
lenOutFast=round(tempoutFast)
endif
if tempoutSlow<1 then
lenOutSlow=1
else
lenOutSlow=round(tempoutSlow)
endif
//-----------------------------------------//
//-----EFI and Signal Calculation----------//
//-----------------------------------------//
if calcType=1 then
efi=average[len,1]((close-close[1])*volume)
sig=average[len,1](efi)
length=len
else
efi=average[lenOutFast,1]((close-close[1])*volume)
sig=average[lenOutSlow,1](efi)
length=lenOutSlow
endif
atrEMA=abs(efi[1]-efi)
src1 = atrEMA
alpha = 1/length
if barindex = 2*length then
atrOUT = average[length](src1)
else
atrOUT = alpha*src1 + (1-alpha)*atrOUT[1]
endif
//-----------------------------------------//
//-----ATR Channel Calculation-------------//
//-----------------------------------------//
atrHigh1=sig+atrOut*atrMult1
atrHigh2=sig+atrOut*atrMult2
atrHigh3=sig+atrOut*atrMult3
atrLow1=sig-atrOut*atrMult1
atrLow2=sig-atrOut*atrMult2
atrLow3=sig-atrOut*atrMult3
atrObHigh=sig+atrOut*(atrMult3+1)
atrObLow=sig-atrOut*(atrMult3+1)
if truncAtr then
if efi>atrObHigh then
efiOut=atrHigh3
else
if efi<atrOblow then
efiOut=atrLow3
else
efiOut=efi
endif
endif
else
efiOut=efi
endif
//-----------------------------------------//
//-----Plot shapes-------------------------//
//-----------------------------------------//
if efiOut>=atrHigh3 then
drawpoint(barindex,efiOut,3)coloured(210,4,45)
elsif efiout<=atrLow3 then
drawpoint(barindex,efiOut,3)coloured(45,210,4)
endif
//-----------------------------------------//
//-----------------------------------------//
//-----------------------------------------//
return efiOut as "EFI" coloured("blue")style(line,2), sig as "Signal" coloured("orange")style(line,2), 0 as "zero"style(dottedline,2)coloured("grey"), atrHigh1 as "ATR1 high"coloured("grey")style(dottedline,1), atrHigh2 as "ATR2 high"coloured("grey")style(dottedline2,1), atrHigh3 as "ATR3 high"coloured("grey")style(line,2), atrLow1 as "ATR1 low"coloured("grey")style(dottedline,1),atrLow2 as "ATR2 low"coloured("grey")style(dottedline2,1),atrLow3 as "ATR3 low"coloured("grey")style(line,2)