mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-25 22:08:05 +00:00
SIMD Refactor: Merge simd-dev into dev (#55)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> Co-authored-by: aider (openrouter/anthropic/claude-sonnet-4) <aider@aider.chat> Co-authored-by: Warp <agent@warp.dev>
This commit is contained in:
co-authored by
Claude Opus 4.5
aider
Warp
parent
5bcdf8d614
commit
86fe32a682
@@ -0,0 +1,90 @@
|
||||
// The MIT License (MIT)
|
||||
// © mihakralj
|
||||
//@version=6
|
||||
indicator("HOMOD: Homodyne Discriminator Dominant Cycle","HOMOD",overlay=false)
|
||||
|
||||
//@function Quadrant-aware angle calculation using stable atan2
|
||||
//@param y Imaginary component
|
||||
//@param x Real component
|
||||
//@returns Angle in radians from -π to π
|
||||
atan2(series float y,series float x)=>
|
||||
if y==0.0 and x==0.0
|
||||
runtime.error("atan2: y and x cannot both be zero")
|
||||
float ay=math.abs(y)
|
||||
float ax=math.abs(x)
|
||||
float angle=0.0
|
||||
if ax>ay
|
||||
angle:=math.atan(ay/ax)
|
||||
else
|
||||
angle:=(math.pi/2.0)-math.atan(ax/ay)
|
||||
if x<0.0
|
||||
angle:=math.pi-angle
|
||||
if y<0.0
|
||||
angle:=-angle
|
||||
angle
|
||||
|
||||
//@function Measures dominant cycle period using Ehlers homodyne discriminator
|
||||
//@param source Price input series
|
||||
//@param minPeriod Minimum dominant cycle length
|
||||
//@param maxPeriod Maximum dominant cycle length
|
||||
//@returns Smoothed dominant cycle estimate
|
||||
//@optimized Exponential warmup compensation for dominant cycle smoothing
|
||||
//@validation wolfram:"atan2(y,x)" external:"TradingView Homodyne Discriminator","Forex-Station Homodyne Discriminator","MQL5 Adaptive Lookback Homodyne","tindicators hd.cc"
|
||||
homod(series float source,simple float minPeriod,simple float maxPeriod)=>
|
||||
if minPeriod<=0
|
||||
runtime.error("Min period must be greater than 0")
|
||||
if maxPeriod<=minPeriod
|
||||
runtime.error("Max period must be greater than min period")
|
||||
var float smooth_price=0.0
|
||||
var float detrender=0.0
|
||||
var float i1=0.0
|
||||
var float q1=0.0
|
||||
var float ji=0.0
|
||||
var float jq=0.0
|
||||
var float i2=0.0
|
||||
var float q2=0.0
|
||||
var float re=0.0
|
||||
var float im=0.0
|
||||
var float period=15.0
|
||||
var float smooth_period=15.0
|
||||
var float warm_decay=1.0
|
||||
var bool warmup=true
|
||||
float price=nz(source)
|
||||
float bandwidth=0.075*smooth_period+0.54
|
||||
smooth_price:=(4.0*price+3.0*nz(price[1])+2.0*nz(price[2])+nz(price[3]))/10.0
|
||||
detrender:=(0.0962*smooth_price+0.5769*nz(smooth_price[2])-0.5769*nz(smooth_price[4])-0.0962*nz(smooth_price[6]))*bandwidth
|
||||
q1:=(0.0962*detrender+0.5769*nz(detrender[2])-0.5769*nz(detrender[4])-0.0962*nz(detrender[6]))*bandwidth
|
||||
i1:=nz(detrender[3])
|
||||
ji:=(0.0962*i1+0.5769*nz(i1[2])-0.5769*nz(i1[4])-0.0962*nz(i1[6]))*bandwidth
|
||||
jq:=(0.0962*q1+0.5769*nz(q1[2])-0.5769*nz(q1[4])-0.0962*nz(q1[6]))*bandwidth
|
||||
float i2_raw=i1-jq
|
||||
float q2_raw=q1+ji
|
||||
i2:=0.2*i2_raw+0.8*nz(i2[1])
|
||||
q2:=0.2*q2_raw+0.8*nz(q2[1])
|
||||
float re_raw=i2*nz(i2[1])+q2*nz(q2[1])
|
||||
float im_raw=i2*nz(q2[1])-q2*nz(i2[1])
|
||||
re:=0.2*re_raw+0.8*nz(re[1])
|
||||
im:=0.2*im_raw+0.8*nz(im[1])
|
||||
float magnitude=math.abs(re)+math.abs(im)
|
||||
if magnitude>1e-10
|
||||
float angle=atan2(im,re)
|
||||
if math.abs(angle)>1e-10
|
||||
float candidate=2.0*math.pi/angle
|
||||
float clamped=math.max(minPeriod,math.min(maxPeriod,math.abs(candidate)))
|
||||
period:=0.2*clamped+0.8*period
|
||||
float alpha=0.33
|
||||
smooth_period:=smooth_period+alpha*(period-smooth_period)
|
||||
float result=smooth_period
|
||||
if warmup
|
||||
warm_decay*=1.0-alpha
|
||||
float denom=1.0-warm_decay
|
||||
result:=denom>1e-10?result/denom:result
|
||||
warmup:=warm_decay>1e-10
|
||||
result
|
||||
|
||||
// ---------- Main loop ----------
|
||||
i_source=input.source(hlc3,"Source")
|
||||
i_minPeriod=input.float(6,"Min Period",minval=1,maxval=5000,step=0.5)
|
||||
i_maxPeriod=input.float(50,"Max Period",minval=2,maxval=5000,step=0.5)
|
||||
homodPeriod=homod(i_source,i_minPeriod,i_maxPeriod)
|
||||
plot(homodPeriod,"Dominant Cycle Period",color=color.yellow,linewidth=2)
|
||||
Reference in New Issue
Block a user