mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-21 03:58:04 +00:00
pine files
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
// The MIT License (MIT)
|
||||
// © mihakralj
|
||||
//@version=6
|
||||
indicator("Awesome Oscillator (AO)", "AO", overlay=false)
|
||||
|
||||
//@function Calculates Bill Williams' Awesome Oscillator
|
||||
//@doc https://github.com/mihakralj/pinescript/blob/main/indicators/oscillators/ao.md
|
||||
//@param fastLength Period for fast MA calculation
|
||||
//@param slowLength Period for slow MA calculation
|
||||
//@returns AO value measuring market momentum
|
||||
ao(simple int fastLength, simple int slowLength) =>
|
||||
if fastLength <= 0 or slowLength <= 0
|
||||
runtime.error("Lengths must be greater than 0")
|
||||
if fastLength >= slowLength
|
||||
runtime.error("Fast length must be less than slow length")
|
||||
float mp = (high + low) / 2.0
|
||||
var array<float> fastBuf = array.new_float(fastLength, na)
|
||||
var array<float> slowBuf = array.new_float(slowLength, na)
|
||||
var int fastHead = 0, var int slowHead = 0
|
||||
var float fastSum = 0.0, var float slowSum = 0.0
|
||||
var int fastCount = 0, var int slowCount = 0
|
||||
float fastOldest = array.get(fastBuf, fastHead)
|
||||
if not na(fastOldest)
|
||||
fastSum -= fastOldest
|
||||
fastCount -= 1
|
||||
if not na(mp)
|
||||
fastSum += mp
|
||||
fastCount += 1
|
||||
array.set(fastBuf, fastHead, mp)
|
||||
fastHead := (fastHead + 1) % fastLength
|
||||
float slowOldest = array.get(slowBuf, slowHead)
|
||||
if not na(slowOldest)
|
||||
slowSum -= slowOldest
|
||||
slowCount -= 1
|
||||
if not na(mp)
|
||||
slowSum += mp
|
||||
slowCount += 1
|
||||
array.set(slowBuf, slowHead, mp)
|
||||
slowHead := (slowHead + 1) % slowLength
|
||||
float fastMA = fastCount > 0 ? fastSum / fastCount : na
|
||||
float slowMA = slowCount > 0 ? slowSum / slowCount : na
|
||||
fastMA - slowMA
|
||||
|
||||
// ---------- Main loop ----------
|
||||
|
||||
// Inputs
|
||||
i_fastLength = input.int(5, "Fast Length", minval=1)
|
||||
i_slowLength = input.int(34, "Slow Length", minval=1)
|
||||
|
||||
// Calculation
|
||||
ao_value = ao(i_fastLength, i_slowLength)
|
||||
ao_prev = ao_value[1]
|
||||
|
||||
// Plot
|
||||
plot(ao_value, "AO", ao_value >= ao_prev ? color.green : color.red, linewidth=2)
|
||||
@@ -0,0 +1,50 @@
|
||||
// The MIT License (MIT)
|
||||
// © mihakralj
|
||||
//@version=6
|
||||
indicator("Absolute Price Oscillator (APO)", "APO", overlay=false)
|
||||
|
||||
//@function Calculates Absolute Price Oscillator (APO) as difference between fast and slow EMAs
|
||||
//@doc https://github.com/mihakralj/pinescript/blob/main/indicators/oscillators/apo.md
|
||||
//@param source Series to calculate APO from
|
||||
//@param fastLength Period for fast EMA
|
||||
//@param slowLength Period for slow EMA
|
||||
//@returns APO value (fast EMA - slow EMA)
|
||||
apo(series float source, simple int fastLength, simple int slowLength) =>
|
||||
if fastLength <= 0 or slowLength <= 0
|
||||
runtime.error("Lengths must be greater than 0")
|
||||
if fastLength >= slowLength
|
||||
runtime.error("Fast length must be less than slow length")
|
||||
float alphaFast = 2.0 / (fastLength + 1.0)
|
||||
float alphaSlow = 2.0 / (slowLength + 1.0)
|
||||
var float emaFast = na var float emaSlow = na, var float e = 1.0
|
||||
var bool warmup = true, var float result = na
|
||||
if not na(source)
|
||||
if na(emaFast)
|
||||
emaFast := source, emaSlow := source, result := 0
|
||||
else
|
||||
emaFast := alphaFast * (source - emaFast) + emaFast
|
||||
emaSlow := alphaSlow * (source - emaSlow) + emaSlow
|
||||
if warmup
|
||||
e *= (1.0 - alphaSlow)
|
||||
float c = e > 1e-10 ? 1.0 / (1.0 - e) : 1.0
|
||||
float aFast = emaFast * c
|
||||
float aSlow = emaSlow * c
|
||||
result := aFast - aSlow
|
||||
if e <= 1e-10
|
||||
warmup := false
|
||||
else
|
||||
result := emaFast - emaSlow
|
||||
result
|
||||
|
||||
// ---------- Main loop ----------
|
||||
|
||||
// Inputs
|
||||
i_source = input.source(close, "Source")
|
||||
i_fastLength = input.int(12, "Fast Length", minval=1)
|
||||
i_slowLength = input.int(26, "Slow Length", minval=1)
|
||||
|
||||
// Calculation
|
||||
apo_value = apo(i_source, i_fastLength, i_slowLength)
|
||||
|
||||
// Plot
|
||||
plot(apo_value, "APO", color.new(color.yellow, 0), 2)
|
||||
@@ -0,0 +1,92 @@
|
||||
// The MIT License (MIT)
|
||||
// © mihakralj
|
||||
//@version=6
|
||||
indicator("Ultimate Oscillator (ULTOSC)", "ULTOSC", overlay=false)
|
||||
|
||||
//@function Calculates the Ultimate Oscillator using three weighted time periods
|
||||
//@doc https://github.com/mihakralj/pinescript/blob/main/indicators/oscillators/ultosc.md
|
||||
//@param fastPeriod Short-term period for momentum calculation
|
||||
//@param mediumPeriod Medium-term period for momentum calculation
|
||||
//@param slowPeriod Long-term period for momentum calculation
|
||||
//@param fastWeight Weight applied to fast period calculation
|
||||
//@param mediumWeight Weight applied to medium period calculation
|
||||
//@param slowWeight Weight applied to slow period calculation
|
||||
//@returns Ultimate Oscillator value (0-100 scale)
|
||||
ultosc(simple int fastPeriod, simple int mediumPeriod, simple int slowPeriod, simple float fastWeight, simple float mediumWeight, simple float slowWeight) =>
|
||||
if fastPeriod <= 0 or mediumPeriod <= 0 or slowPeriod <= 0
|
||||
runtime.error("All periods must be positive")
|
||||
if fastPeriod >= mediumPeriod or mediumPeriod >= slowPeriod
|
||||
runtime.error("Periods must be in ascending order: fast < medium < slow")
|
||||
if fastWeight <= 0 or mediumWeight <= 0 or slowWeight <= 0
|
||||
runtime.error("All weights must be positive")
|
||||
prev_close = nz(close[1], close)
|
||||
true_low = math.min(low, prev_close)
|
||||
true_high = math.max(high, prev_close)
|
||||
buying_pressure = close - true_low
|
||||
true_range = true_high - true_low
|
||||
var array<float> bp_fast_buffer = array.new_float(fastPeriod, na)
|
||||
var array<float> tr_fast_buffer = array.new_float(fastPeriod, na)
|
||||
var array<float> bp_medium_buffer = array.new_float(mediumPeriod, na)
|
||||
var array<float> tr_medium_buffer = array.new_float(mediumPeriod, na)
|
||||
var array<float> bp_slow_buffer = array.new_float(slowPeriod, na)
|
||||
var array<float> tr_slow_buffer = array.new_float(slowPeriod, na)
|
||||
var int fast_head = 0, var int medium_head = 0, var int slow_head = 0
|
||||
var float bp_fast_sum = 0.0, var float tr_fast_sum = 0.0
|
||||
var float bp_medium_sum = 0.0, var float tr_medium_sum = 0.0
|
||||
var float bp_slow_sum = 0.0, var float tr_slow_sum = 0.0
|
||||
var int fast_count = 0, var int medium_count = 0, var int slow_count = 0
|
||||
bp_fast_oldest = array.get(bp_fast_buffer, fast_head)
|
||||
tr_fast_oldest = array.get(tr_fast_buffer, fast_head)
|
||||
bp_fast_sum := not na(bp_fast_oldest) ? bp_fast_sum - bp_fast_oldest : bp_fast_sum
|
||||
tr_fast_sum := not na(tr_fast_oldest) ? tr_fast_sum - tr_fast_oldest : tr_fast_sum
|
||||
fast_count := not na(bp_fast_oldest) ? fast_count - 1 : fast_count
|
||||
bp_fast_sum := not na(buying_pressure) ? bp_fast_sum + buying_pressure : bp_fast_sum
|
||||
tr_fast_sum := not na(true_range) ? tr_fast_sum + true_range : tr_fast_sum
|
||||
fast_count := not na(buying_pressure) ? fast_count + 1 : fast_count
|
||||
array.set(bp_fast_buffer, fast_head, buying_pressure)
|
||||
array.set(tr_fast_buffer, fast_head, true_range)
|
||||
fast_head := (fast_head + 1) % fastPeriod
|
||||
bp_medium_oldest = array.get(bp_medium_buffer, medium_head)
|
||||
tr_medium_oldest = array.get(tr_medium_buffer, medium_head)
|
||||
bp_medium_sum := not na(bp_medium_oldest) ? bp_medium_sum - bp_medium_oldest : bp_medium_sum
|
||||
tr_medium_sum := not na(tr_medium_oldest) ? tr_medium_sum - tr_medium_oldest : tr_medium_sum
|
||||
medium_count := not na(bp_medium_oldest) ? medium_count - 1 : medium_count
|
||||
bp_medium_sum := not na(buying_pressure) ? bp_medium_sum + buying_pressure : bp_medium_sum
|
||||
tr_medium_sum := not na(true_range) ? tr_medium_sum + true_range : tr_medium_sum
|
||||
medium_count := not na(buying_pressure) ? medium_count + 1 : medium_count
|
||||
array.set(bp_medium_buffer, medium_head, buying_pressure)
|
||||
array.set(tr_medium_buffer, medium_head, true_range)
|
||||
medium_head := (medium_head + 1) % mediumPeriod
|
||||
bp_slow_oldest = array.get(bp_slow_buffer, slow_head)
|
||||
tr_slow_oldest = array.get(tr_slow_buffer, slow_head)
|
||||
bp_slow_sum := not na(bp_slow_oldest) ? bp_slow_sum - bp_slow_oldest : bp_slow_sum
|
||||
tr_slow_sum := not na(tr_slow_oldest) ? tr_slow_sum - tr_slow_oldest : tr_slow_sum
|
||||
slow_count := not na(bp_slow_oldest) ? slow_count - 1 : slow_count
|
||||
bp_slow_sum := not na(buying_pressure) ? bp_slow_sum + buying_pressure : bp_slow_sum
|
||||
tr_slow_sum := not na(true_range) ? tr_slow_sum + true_range : tr_slow_sum
|
||||
slow_count := not na(buying_pressure) ? slow_count + 1 : slow_count
|
||||
array.set(bp_slow_buffer, slow_head, buying_pressure)
|
||||
array.set(tr_slow_buffer, slow_head, true_range)
|
||||
slow_head := (slow_head + 1) % slowPeriod
|
||||
raw_fast = tr_fast_sum > 0 and fast_count >= fastPeriod ? 100 * bp_fast_sum / tr_fast_sum : 0
|
||||
raw_medium = tr_medium_sum > 0 and medium_count >= mediumPeriod ? 100 * bp_medium_sum / tr_medium_sum : 0
|
||||
raw_slow = tr_slow_sum > 0 and slow_count >= slowPeriod ? 100 * bp_slow_sum / tr_slow_sum : 0
|
||||
total_weight = fastWeight + mediumWeight + slowWeight
|
||||
weighted_sum = (raw_fast * fastWeight) + (raw_medium * mediumWeight) + (raw_slow * slowWeight)
|
||||
slow_count >= slowPeriod ? weighted_sum / total_weight : na
|
||||
|
||||
// ---------- Main loop ----------
|
||||
|
||||
// Inputs
|
||||
i_fastPeriod = input.int(7, "Fast Period", minval=1, maxval=50, tooltip="Short-term period for momentum calculation")
|
||||
i_mediumPeriod = input.int(14, "Medium Period", minval=1, maxval=100, tooltip="Medium-term period for momentum calculation")
|
||||
i_slowPeriod = input.int(28, "Slow Period", minval=1, maxval=200, tooltip="Long-term period for momentum calculation")
|
||||
i_fastWeight = input.float(4.0, "Fast Weight", minval=0.1, maxval=10.0, step=0.1, tooltip="Weight applied to fast period calculation")
|
||||
i_mediumWeight = input.float(2.0, "Medium Weight", minval=0.1, maxval=10.0, step=0.1, tooltip="Weight applied to medium period calculation")
|
||||
i_slowWeight = input.float(1.0, "Slow Weight", minval=0.1, maxval=10.0, step=0.1, tooltip="Weight applied to slow period calculation")
|
||||
|
||||
// Calculation
|
||||
ultosc_value = ultosc(i_fastPeriod, i_mediumPeriod, i_slowPeriod, i_fastWeight, i_mediumWeight, i_slowWeight)
|
||||
|
||||
// Plots
|
||||
plot(ultosc_value, "Ultimate Oscillator", color=color.yellow, linewidth=2)
|
||||
Reference in New Issue
Block a user