PHP Code:
//@version=6
indicator(":]", overlay=true, max_lines_count=50, max_labels_count=500)
///////////////////////
// ==========================================
// 1. AYARLAR
// ==========================================
float ayar_genislik = input.float(1.5, "Genilik (0.1 - 2.0)", minval=0.1, maxval=2.0, step=0.1)
// ==========================================
// 2. ANA OMURGA MOTORU (HMA 55)
// ==========================================
float s_start_sabit = 0.02
float s_inc_sabit = 0.02
float s_max_sabit = 0.2
int s_smooth_sabit = 100
f_katman_ana(_start, _inc, _max, _smooth) =>
float _sar = ta.sar(_start, _inc, _max)
float _delta = math.abs(close - _sar)
bool _is_up = close > _sar
float _raw_mirror = _is_up ? close + _delta : close - _delta
ta.hma(_raw_mirror, _smooth)
float mirror_ana = f_katman_ana(s_start_sabit, s_inc_sabit, s_max_sabit, s_smooth_sabit)
// ==========================================
// 3. MOTOR BLOKLARI (SAR PARAMETRELER)
// ==========================================
float s_slow_1 = ta.sar(0.02, 0.02, 0.2)
float s_slow_2 = ta.sar(0.015, 0.015, 0.15)
float s_slow_3 = ta.sar(0.01, 0.01, 0.1)
float s_fast_1 = ta.sar(0.08, 0.05, 0.2)
float s_fast_2 = ta.sar(0.01, 0.05, 0.2)
float s_fast_3 = ta.sar(0.04, 0.04, 0.2)
float avg_fast = (s_fast_1 + s_fast_2 + s_fast_3) / 3
// ==========================================
// 4. YAPAY ZEKA (DL) MODL (SRTNMESZ)
// ==========================================
tanh_fn(v) => (1 - math.exp(-2 * v)) / (1 + math.exp(-2 * v))
td_fn(s) => nz((s - nz(s[1])) / nz(s[1]))
float in_o = tanh_fn(td_fn(open))
float in_h = tanh_fn(td_fn(high))
float in_l = tanh_fn(td_fn(low))
float in_c = tanh_fn(td_fn(close))
float h0 = tanh_fn((in_o * 22.4271) + (in_h * -26.6917) + (in_l * 4.9371) + (in_c * 9.0349) - 10.6929)
float h1 = tanh_fn((in_o * -38.2880) + (in_h * 10.0500) + (in_l * -44.7063) + (in_c * -17.8163) + 30.5662)
float h2 = tanh_fn((in_o * -33.9954) + (in_h * 14.5017) + (in_l * -43.2865) + (in_c * -13.3874) + 24.7080)
float h3 = tanh_fn((in_o * -14.3929) + (in_h * 28.4830) + (in_l * -22.9793) + (in_c * -7.6582) - 5.6505)
float h4 = tanh_fn((in_o * 28.8379) + (in_h * -26.3544) + (in_l * 0.5206) + (in_c * 25.0049) - 17.8832)
float h5 = tanh_fn((in_o * -4.8113) + (in_h * -4.0364) + (in_l * -8.3327) + (in_c * -1.1571) + 0.4667)
float dl_val = tanh_fn((h0 * -22.0533) + (h1 * 3.6525) + (h2 * -4.3904) + (h3 * 2.1030) + (h4 * 20.0272) + (h5 * 11.5101) - 0.4150)
float ai_factor = (0.2 + (math.abs(dl_val) * 0.5)) * ayar_genislik
// ==========================================
// 5. DNAMK RENKL ATMOSFER VE KALKAN
// ==========================================
bool all_fast_below = (close > s_fast_1) and (close > s_fast_2) and (close > s_fast_3)
bool all_fast_above = (close < s_fast_1) and (close < s_fast_2) and (close < s_fast_3)
color core_color = all_fast_below ? color.new(color.green, 50) :
all_fast_above ? color.new(color.red, 50) :
color.new(color.yellow, 50)
float dist_1 = math.abs(close - s_fast_1) * ai_factor
float l1_top = close + dist_1
float l1_bot = close - dist_1
p1_top = plot(l1_top, "st", display=display.none)
p1_bot = plot(l1_bot, "Alt", display=display.none)
fill(p1_top, p1_bot, color=core_color, title="Dinamik ekirdek ")
int kalkan = 0
if close > s_fast_1
kalkan += 1
if close > s_fast_2
kalkan += 1
if close > s_fast_3
kalkan += 1
if close < s_fast_1 and close < avg_fast
kalkan += 1
if close < s_fast_2 and close < avg_fast
kalkan += 1
if close < s_fast_3 and close < avg_fast
kalkan += 1
color bar_col = na
if kalkan >= 3
bar_col := close > avg_fast ? color.rgb(0, 230, 119, 100) : color.rgb(255, 82, 82, 100)
else if kalkan == 2
bar_col := color.rgb(0, 0, 0)
else
bar_col := color.rgb(223, 64, 251, 100)
barcolor(bar_col)
// ==========================================
// 6. ANA OMURGA RENK MANTII
// ==========================================
bool makro_al = mirror_ana > close
color col_mirror_ana = na
if makro_al
if mirror_ana < mirror_ana[1]
col_mirror_ana := color.blue
else
col_mirror_ana := color.lime
else
if mirror_ana > mirror_ana[1]
col_mirror_ana := color.yellow
else
col_mirror_ana := color.red
// ==========================================
// 7. HAFIZALI SNYAL MANTII VE TAKP
// ==========================================
bool is_sari = (col_mirror_ana == color.yellow)
bool is_mavi = (col_mirror_ana == color.blue)
var int sinyal_durumu = 0
bool kesin_al = false
bool kesin_sat = false
var string son_yon = "BEKLENYOR"
var float son_sinyal_fiyati = na
if barstate.isconfirmed
if is_sari and sinyal_durumu != 1
kesin_al := true
sinyal_durumu := 1
son_yon := "AL"
son_sinyal_fiyati := close
if is_mavi and sinyal_durumu != -1
kesin_sat := true
sinyal_durumu := -1
son_yon := "SAT"
son_sinyal_fiyati := close
// ==========================================
// 8. FT YNL EVREKA MANTII (TAVAN VE ZEMN)
// ==========================================
var float evreka_tepe = na
var float evreka_dip = na
// Renklere deil, dorudan ekirdei oluturan matematiksel manta kilitledik!
bool is_green_core = all_fast_below
bool is_red_core = all_fast_above
// TAVAN: Yeil atmosferin en yksek noktas
if is_green_core
evreka_tepe := na(evreka_tepe) ? l1_top : math.max(evreka_tepe, l1_top)
// ZEMN: Krmz atmosferin en dk noktas
if is_red_core
evreka_dip := na(evreka_dip) ? l1_bot : math.min(evreka_dip, l1_bot)
// TREND DNNDE HAFIZALARI SIFIRLAMA
if close < s_slow_1
evreka_tepe := na
if close > s_slow_1
evreka_dip := na
// KIRILIMLAR
bool evreka_direnc_kirilim = ta.crossover(mirror_ana, evreka_tepe) and barstate.isconfirmed
bool evreka_destek_kirilim = ta.crossunder(mirror_ana, evreka_dip) and barstate.isconfirmed
// ==========================================
// 9. GRSELLETRME VE ALARMLAR
// ==========================================
plot(mirror_ana, "0", color=col_mirror_ana, linewidth=3, style=plot.style_stepline)
plot(evreka_tepe, "+1", color=color.new(color.fuchsia, 100), style=plot.style_linebr, linewidth=2)
plot(evreka_dip, "-1", color=color.new(color.fuchsia, 100), style=plot.style_linebr, linewidth=2)
//plotshape(kesin_al, "Sar Balad (AL)", shape.labelup, location.belowbar, color.rgb(255, 235, 59), text="L", textcolor=color.black, size=size.tiny)
//plotshape(kesin_sat, "Mavi Balad (SAT)", shape.labeldown, location.abovebar, color.rgb(33, 150, 243), text="S", textcolor=color.white, size=size.tiny)
// ift Ynl Evreka Bayraklar
//plotshape(evreka_direnc_kirilim, "(@yrk@) DREN", shape.flag, location.abovebar, color.fuchsia, text="DR\n(@yrk@)", textcolor=color.fuchsia, size=size.small)
//plotshape(evreka_destek_kirilim, "(@yrk@) DESTEK", shape.flag, location.belowbar, color.fuchsia, text="DES\n(@yrk@)", textcolor=color.fuchsia, size=size.small)
//alertcondition(evreka_direnc_kirilim, title="💎 EVREKA (KOPU!)", message="Sistem: Ana Trend, ekirdek Tepeyi at!")
//alertcondition(evreka_destek_kirilim, title="⚠️ EVREKA (K!)", message="Sistem: Ana Trend, ekirdek Dibi aa krd!")
// ==========================================
// 10. KOMUTA MERKEZ (DASHBOARD)
// ==========================================
var table dash = table.new(position.top_right, 3, 14, border_width = 1, border_color = color.new(color.gray, 80))
if barstate.islast
table.cell(dash, 0, 0, "Yatrm Tavsiyesi DELDR.", text_color=color.white, bgcolor=color.new(color.black, 20), text_size=size.normal, text_halign=text.align_center)
table.merge_cells(dash, 0, 0, 2, 0)
table.cell(dash, 0, 1, "Fiyat:", text_color=color.gray, bgcolor=color.new(color.black, 40), text_halign=text.align_left)
table.cell(dash, 1, 1, str.tostring(close, format.mintick), text_color=color.white, bgcolor=color.new(color.black, 40), text_halign=text.align_right)
table.merge_cells(dash, 1, 1, 2, 1)
string sig_text = son_yon == "BEKLENYOR" ? "YOK" : son_yon + " @ " + str.tostring(son_sinyal_fiyati, format.mintick)
color sig_color = son_yon == "AL" ? color.rgb(255, 235, 59) : son_yon == "SAT" ? color.rgb(33, 150, 243) : color.gray
table.cell(dash, 0, 2, "Son Sinyal:", text_color=color.gray, bgcolor=color.new(color.black, 40), text_halign=text.align_left)
table.cell(dash, 1, 2, sig_text, text_color=sig_color, bgcolor=color.new(color.black, 40), text_halign=text.align_right)
table.merge_cells(dash, 1, 2, 2, 2)
table.cell(dash, 0, 3, "Trend:", text_color=color.gray, bgcolor=color.new(color.black, 40), text_halign=text.align_left)
table.cell(dash, 1, 3, str.tostring(mirror_ana, format.mintick), text_color=col_mirror_ana, bgcolor=color.new(color.black, 40), text_halign=text.align_right)
table.merge_cells(dash, 1, 3, 2, 3)
string evreka_tepe_str = na(evreka_tepe) ? "BEKLENYOR" : str.tostring(evreka_tepe, format.mintick)
table.cell(dash, 0, 4, "Oto Diren:", text_color=color.fuchsia, bgcolor=color.new(color.black, 40), text_halign=text.align_left)
table.cell(dash, 1, 4, evreka_tepe_str, text_color=color.fuchsia, bgcolor=color.new(color.black, 40), text_halign=text.align_right)
table.merge_cells(dash, 1, 4, 2, 4)
string evreka_dip_str = na(evreka_dip) ? "BEKLENYOR" : str.tostring(evreka_dip, format.mintick)
table.cell(dash, 0, 5, "Oto Destek:", text_color=color.fuchsia, bgcolor=color.new(color.black, 40), text_halign=text.align_left)
table.cell(dash, 1, 5, evreka_dip_str, text_color=color.fuchsia, bgcolor=color.new(color.black, 40), text_halign=text.align_right)
table.merge_cells(dash, 1, 5, 2, 5)
table.cell(dash, 0, 6, "--- A-HIZLI (@yrk@) ---", text_color=color.yellow, bgcolor=color.new(color.black, 20), text_halign=text.align_center)
table.merge_cells(dash, 0, 6, 2, 6)
table.cell(dash, 0, 7, "1:", text_color=color.gray, bgcolor=color.new(color.black, 40), text_halign=text.align_left)
table.cell(dash, 1, 7, str.tostring(s_fast_1, format.mintick), text_color=color.white, bgcolor=color.new(color.black, 40), text_halign=text.align_right)
table.cell(dash, 2, 7, close > s_fast_1 ? "AL" : "SAT", text_color=close > s_fast_1 ? color.lime : color.red, bgcolor=color.new(color.black, 40), text_halign=text.align_center)
table.cell(dash, 0, 8, "2:", text_color=color.gray, bgcolor=color.new(color.black, 40), text_halign=text.align_left)
table.cell(dash, 1, 8, str.tostring(s_fast_2, format.mintick), text_color=color.white, bgcolor=color.new(color.black, 40), text_halign=text.align_right)
table.cell(dash, 2, 8, close > s_fast_2 ? "AL" : "SAT", text_color=close > s_fast_2 ? color.lime : color.red, bgcolor=color.new(color.black, 40), text_halign=text.align_center)
table.cell(dash, 0, 9, "3:", text_color=color.gray, bgcolor=color.new(color.black, 40), text_halign=text.align_left)
table.cell(dash, 1, 9, str.tostring(s_fast_3, format.mintick), text_color=color.white, bgcolor=color.new(color.black, 40), text_halign=text.align_right)
table.cell(dash, 2, 9, close > s_fast_3 ? "AL" : "SAT", text_color=close > s_fast_3 ? color.lime : color.red, bgcolor=color.new(color.black, 40), text_halign=text.align_center)
table.cell(dash, 0, 10, "--- A-YAVA (@yrk@) ---", text_color=color.yellow, bgcolor=color.new(color.black, 20), text_halign=text.align_center)
table.merge_cells(dash, 0, 10, 2, 10)
table.cell(dash, 0, 11, "4:", text_color=color.gray, bgcolor=color.new(color.black, 40), text_halign=text.align_left)
table.cell(dash, 1, 11, str.tostring(s_slow_1, format.mintick), text_color=color.white, bgcolor=color.new(color.black, 40), text_halign=text.align_right)
table.cell(dash, 2, 11, close > s_slow_1 ? "AL" : "SAT", text_color=close > s_slow_1 ? color.lime : color.red, bgcolor=color.new(color.black, 40), text_halign=text.align_center)
table.cell(dash, 0, 12, "5:", text_color=color.gray, bgcolor=color.new(color.black, 40), text_halign=text.align_left)
table.cell(dash, 1, 12, str.tostring(s_slow_2, format.mintick), text_color=color.white, bgcolor=color.new(color.black, 40), text_halign=text.align_right)
table.cell(dash, 2, 12, close > s_slow_2 ? "AL" : "SAT", text_color=close > s_slow_2 ? color.lime : color.red, bgcolor=color.new(color.black, 40), text_halign=text.align_center)
table.cell(dash, 0, 13, "6:", text_color=color.gray, bgcolor=color.new(color.black, 40), text_halign=text.align_left)
table.cell(dash, 1, 13, str.tostring(s_slow_3, format.mintick), text_color=color.white, bgcolor=color.new(color.black, 40), text_halign=text.align_right)
table.cell(dash, 2, 13, close > s_slow_3 ? "AL" : "SAT", text_color=close > s_slow_3 ? color.lime : color.red, bgcolor=color.new(color.black, 40), text_halign=text.align_center)
var table ytd_table = table.new(position.bottom_center, 1, 1)
if barstate.islast
table.cell(ytd_table, 0, 0, "(A) - Eitim almasdr. Yatrm tavsiyesi KULLANILAMAZ.", text_color=color.new(color.white, 00), text_size=size.small)
////////////////////
// ┌────────────────────────────── 1. SEL TAZYK: PSAR ─────────────────────────────┐
sarStart = input.float(0.01, "Basn Balangc")
sarInc = input.float(0.02, "Basn vmesi")
sarMax = input.float(0.2, "Maksimum Tazyik")
psarVal = ta.sar(sarStart, sarInc, sarMax)
// ┌────────────────────────────── 2. FZKSEL DREN: KABUK ─────────────────────────┐
direncPeriyodu = input.int(2, "Kapakk (Snr) Periyodu")
ustKapak = ta.highest(high, direncPeriyodu)[1]
altKapak = ta.lowest(low, direncPeriyodu)[1]
// ┌────────────────────────────── 3. MTK-3: FTE KIRILIM ───────────────────────────┐
ciftKirilimAtim = ta.crossover(close, psarVal) and (close > ustKapak)
ciftKirilimGevseme = ta.crossunder(close, psarVal) and (close < altKapak)
// ┌────────────────────────────── 4. MUTLAK HEDEFLER (EVREKA) ───────────────────────┐
// Tahmin (forecast) yok. Krlm anndaki mutlak gemi u nokta hedeftir.
var float tepeHedef = na
var float dipHedef = na
// Kan pompalandnda (Yukar Krlm), geride kalan en derin nefes boluu DP HEDEF olur.
if ciftKirilimAtim
dipHedef := ta.lowest(low, direncPeriyodu * 2)[1]
// Sistem gevediinde (Aa Krlm), geride kalan en ikin kapasite TEPE HEDEF olur.
if ciftKirilimGevseme
tepeHedef := ta.highest(high, direncPeriyodu * 2)[1]
// ┌────────────────────────────── GRSELLETRME ────────────────────────────────────┐
plot(psarVal, "@yrk@", style=plot.style_cross, color=close > psarVal ? color.yellow : color.blue, linewidth=2)
//plot(ustKapak, "st Kapakk", color=color.new(color.gray, 60), style=plot.style_stepline)
//plot(altKapak, "Alt Kapakk", color=color.new(color.gray, 60), style=plot.style_stepline)
// Hedef izgileri (Gelecee uzanan sabit ller)
plot(tepeHedef, "O-Tepe ", color=color.new(color.blue, 30), style=plot.style_linebr, linewidth=1)
plot(dipHedef, "O-Dip ", color=color.new(color.yellow, 30), style=plot.style_linebr, linewidth=1)
//plotshape(ciftKirilimAtim, "MTK-3 Atm", shape.triangleup, location.belowbar, color.teal, size=size.normal)
//plotshape(ciftKirilimGevseme, "MTK-3 Geveme", shape.triangledown, location.abovebar, color.maroon, size=size.normal)
// Daire Formu Dngs
var int mtkDongu = 0
if ciftKirilimAtim
mtkDongu := 1
else if ciftKirilimGevseme
mtkDongu := -1
bgcolor(mtkDongu == 1 ? color.new(color.lime, 90) : mtkDongu == -1 ? color.new(color.red, 90) : na, title="Dng Formu")
///////////////////////
// ┌────────────────────────────── BOSWaves ─ Groups ─────────────────────────────────┐
// └──────────────────────────────────────────────────────────────────────────────────┘
GRP_PSAR = "PSAR Settings"
GRP_KMEANS = "K-Means Regime Detection"
GRP_KNN = "KNN Signal Validation"
GRP_SMOOTH = "Smoothing Settings"
GRP_VISUAL = "Visual Settings"
// ┌────────────────────────────── BOSWaves ─ Tooltips ───────────────────────────────┐
// └──────────────────────────────────────────────────────────────────────────────────┘
// ── PSAR ──
const string tt_base_start = "The initial Acceleration Factor value when a new trend begins. Lower values make the SAR start further from price, giving the trend more room before flipping."
const string tt_base_increment = "How much the AF increases each time price makes a new extreme. Higher values cause the SAR to accelerate toward price more quickly as the trend matures."
const string tt_base_max = "The maximum value the AF can reach. Caps how tightly the SAR trails price, preventing it from becoming too sensitive during extended trends."
// ── K-Means ──
const string tt_use_kmeans = "When enabled, the indicator classifies the market into choppy, neutral, or trending regimes and adjusts PSAR parameters accordingly. Disable to use fixed base AF values throughout."
const string tt_training_period = "How many bars of historical data the regime classifier looks back over to measure flip frequency. Longer periods give more stable regime readings but are slower to react to market changes."
const string tt_choppy_threshold = "Percentile of the flip-frequency range used as the choppy market centroid. At 0.75, a flip frequency in the upper 25% of its historical range is classified as choppy. Higher = harder to enter choppy regime."
const string tt_trending_threshold = "Percentile of the flip-frequency range used as the trending market centroid. At 0.25, a flip frequency in the lower 25% of its historical range is classified as trending. Lower = harder to enter trending regime."
// ── KNN ──
const string tt_use_knn = "When enabled, each SAR flip is scored using K-Nearest Neighbors on historical flips. The score reflects how often similar past setups led to a successful reversal. Disable to treat all flips equally."
const string tt_k_neighbors = "How many of the closest historical matches to include when computing the confidence score. More neighbors = smoother, more stable scores. Fewer = more sensitive to individual historical examples."
const string tt_knn_lookback = "How far back (in bars) the KNN search scans for historical flip comparisons. Larger values give the model more examples to learn from but increase computation time."
const string tt_min_confidence = "KNN confidence score threshold (0100). Flips scoring below this value are treated as low-confidence they still appear on the chart but are excluded from high-confidence alerts."
// ── Smoothing ──
const string tt_use_af_smoothing = "Instead of incrementing the AF in discrete steps, this ramps it gradually using exponential smoothing. Produces a more fluid SAR line that is less prone to sudden jumps."
const string tt_af_smooth_alpha = "Controls how quickly the AF ramps toward its target on each bar. 1.0 = no smoothing (instant step). 0.01 = very gradual ramp. Has no effect if AF Smoothing is disabled."
const string tt_use_kalman = "Applies a Kalman filter to the SAR output to smooth the displayed dot positions. The filter snaps to the new SAR value on every flip so reversals are not delayed, then re-smooths from that point."
const string tt_kalman_proc_noise = "Controls how much the Kalman filter trusts the SAR's own dynamics versus measurements. Higher values cause the filter to adapt faster to SAR changes, reducing smoothing lag."
const string tt_kalman_meas_noise = "Controls how much the Kalman filter smooths the SAR line. Higher values apply more smoothing and make the line less responsive to each new SAR value. Lower values track the raw SAR more closely."
const string tt_use_min_bars = "Prevents SAR flips from occurring unless the current trend has lasted at least a minimum number of bars. Reduces whipsaws in fast, choppy markets."
const string tt_min_flip_bars = "The minimum number of bars a trend must run before a SAR flip is allowed. For example, 3 means the first two bars of a new trend are always protected from an immediate reversal."
// ── Visual ──
const string tt_bull_color = "Color used for the SAR dots, fill, and labels when the trend is bullish (SAR below price)."
const string tt_bear_color = "Color used for the SAR dots, fill, and labels when the trend is bearish (SAR above price)."
const string tt_show_confidence_labels = "Displays the KNN confidence percentage next to each flip label. Green = 70%+, Orange = 5069%, Red = below 50%. Only visible when KNN Signal Scoring is enabled."
const string tt_show_regime_labels = "Displays the current market regime as a number on each bar: 3 = Trending, 2 = Neutral, 1 = Choppy. Useful for understanding how the K-Means system is classifying the market in real time."
// ┌────────────────────────────── BOSWaves ─ Inputs ─────────────────────────────────┐
// └──────────────────────────────────────────────────────────────────────────────────┘
base_start = input.float(0.02, "Base AF Start", minval=0.001, step=0.001, group=GRP_PSAR, tooltip=tt_base_start)
base_increment = input.float(0.02, "Base AF Increment", minval=0.001, step=0.001, group=GRP_PSAR, tooltip=tt_base_increment)
base_max = input.float(0.2, "Base AF Maximum", step=0.01, group=GRP_PSAR, tooltip=tt_base_max)
use_kmeans = input.bool(true, "Enable K-Means Adaptation", group=GRP_KMEANS, tooltip=tt_use_kmeans)
training_period = input.int(100, "Training Data Period", minval=20, maxval=500, group=GRP_KMEANS, tooltip=tt_training_period)
choppy_threshold = input.float(0.75, "Choppy Regime Percentile", maxval=1, group=GRP_KMEANS, tooltip=tt_choppy_threshold)
trending_threshold = input.float(0.25, "Trending Regime Percentile", maxval=1, group=GRP_KMEANS, tooltip=tt_trending_threshold)
use_knn = input.bool(true, "Enable KNN Signal Scoring", group=GRP_KNN, tooltip=tt_use_knn)
k_neighbors = input.int(8, "K - Number of Neighbors", minval=1, maxval=50, group=GRP_KNN, tooltip=tt_k_neighbors)
knn_lookback = input.int(200, "Historical Lookback Period", minval=50, maxval=500, group=GRP_KNN, tooltip=tt_knn_lookback)
min_confidence = input.float(15.0, "Minimum Confidence Filter", minval=0, maxval=100, group=GRP_KNN, tooltip=tt_min_confidence)
use_af_smoothing = input.bool(true, "Enable AF Smoothing", group=GRP_SMOOTH, tooltip=tt_use_af_smoothing)
af_smooth_alpha = input.float(0.01, "AF Smoothing Factor (lower = smoother)", minval=0.01, step=0.05, group=GRP_SMOOTH, tooltip=tt_af_smooth_alpha)
use_kalman = input.bool(true, "Enable Kalman Filter", group=GRP_SMOOTH, tooltip=tt_use_kalman)
kalman_process_noise = input.float(0.015, "Kalman Process Noise", minval=0.001, maxval=0.5, step=0.005, group=GRP_SMOOTH, tooltip=tt_kalman_proc_noise)
kalman_measurement_noise = input.float(0.5, "Kalman Measurement Noise", minval=0.01, maxval=5.0, step=0.1, group=GRP_SMOOTH, tooltip=tt_kalman_meas_noise)
use_min_bars = input.bool(true, "Enable Minimum Bars Filter", group=GRP_SMOOTH, tooltip=tt_use_min_bars)
min_flip_bars = input.int(3, "Minimum Bars Before Flip", minval=1, maxval=20, group=GRP_SMOOTH, tooltip=tt_min_flip_bars)
bull_color = input.color(#00C8FF, "Bullish", group=GRP_VISUAL, inline="col", tooltip=tt_bull_color)
bear_color = input.color(#FF005D, "Bearish", group=GRP_VISUAL, inline="col", tooltip=tt_bear_color)
show_confidence_labels = input.bool(true, "Show Confidence Scores", group=GRP_VISUAL, tooltip=tt_show_confidence_labels)
show_regime_labels = input.bool(true, "Show Regime Numbers", group=GRP_VISUAL, tooltip=tt_show_regime_labels)
// ┌────────────────────────────── BOSWaves ─ Variables ──────────────────────────────┐
// └──────────────────────────────────────────────────────────────────────────────────┘
var float sar = na
var float af = na
var float ep = na
var int trend = 1
var int bars_since_flip = 0
var float af_at_last_flip = 0.0
var int last_trend_duration = 0
var int current_trend_bars = 0
var float ep_progress = 0.0
var float flip_ep = na
var int recent_flips = 0
var float signal_confidence = 50.0
// ── Kalman State Variables ──
var float kalman_estimate = na
var float kalman_error = 1.0
// ┌────────────────────────────── BOSWaves ─ Initialization ─────────────────────────┐
// └──────────────────────────────────────────────────────────────────────────────────┘
if na(sar)
sar := high[1]
af := base_start
ep := low
trend := -1
bars_since_flip := 0
current_trend_bars := 0
bool raw_bull_flip = false
bool raw_bear_flip = false
current_trend_bars += 1
bars_since_flip += 1
// ┌────────────────────────────── BOSWaves ─ PSAR Calculation ───────────────────────┐
// └──────────────────────────────────────────────────────────────────────────────────┘
if trend == 1
if high > ep
ep_progress := (high - flip_ep) / nz(ta.atr(14), high - low)
ep := high
float target_af = math.min(af + base_increment, base_max)
af := use_af_smoothing ? af + af_smooth_alpha * (target_af - af) : target_af
sar := sar + af * (ep - sar)
sar := math.min(sar, low[1])
if bar_index > 1
sar := math.min(sar, low[2])
if close < sar
bool allow_flip = not use_min_bars or current_trend_bars >= min_flip_bars
if allow_flip
raw_bear_flip := true
last_trend_duration := current_trend_bars
af_at_last_flip := af
trend := -1
sar := ep
flip_ep := ep
ep := low
af := base_start
current_trend_bars := 0
bars_since_flip := 0
ep_progress := 0.0
recent_flips += 1
else
if low < ep
ep_progress := (flip_ep - low) / nz(ta.atr(14), high - low)
ep := low
float target_af = math.min(af + base_increment, base_max)
af := use_af_smoothing ? af + af_smooth_alpha * (target_af - af) : target_af
sar := sar - af * (sar - ep)
sar := math.max(sar, high[1])
if bar_index > 1
sar := math.max(sar, high[2])
if close > sar
bool allow_flip = not use_min_bars or current_trend_bars >= min_flip_bars
if allow_flip
raw_bull_flip := true
last_trend_duration := current_trend_bars
af_at_last_flip := af
trend := 1
sar := ep
flip_ep := ep
ep := high
af := base_start
current_trend_bars := 0
bars_since_flip := 0
ep_progress := 0.0
recent_flips += 1
// ┌────────────────────────────── BOSWaves ─ Kalman Filter ──────────────────────────┐
// └──────────────────────────────────────────────────────────────────────────────────┘
if na(kalman_estimate)
kalman_estimate := sar
kalman_error := 1.0
if use_kalman
if raw_bull_flip or raw_bear_flip
kalman_estimate := sar
kalman_error := 1.0
else
float kalman_gain = kalman_error / (kalman_error + kalman_measurement_noise)
kalman_estimate := kalman_estimate + kalman_gain * (sar - kalman_estimate)
kalman_error := (1.0 - kalman_gain) * kalman_error + kalman_process_noise
float display_sar = use_kalman ? kalman_estimate : sar
// ┌────────────────────────────── BOSWaves ─ K-Means Regime Detection ───────────────┐
// └──────────────────────────────────────────────────────────────────────────────────┘
bool had_flip_long_ago = (raw_bull_flip[training_period] or raw_bear_flip[training_period])
if had_flip_long_ago
recent_flips -= 1
recent_flips := math.max(0, recent_flips)
float flip_frequency = recent_flips / training_period * 100
float ff_upper = ta.highest(flip_frequency, training_period)
float ff_lower = ta.lowest(flip_frequency, training_period)
float choppy_centroid = ff_lower + (ff_upper - ff_lower) * choppy_threshold
float neutral_centroid = ff_lower + (ff_upper - ff_lower) * 0.5
float trending_centroid = ff_lower + (ff_upper - ff_lower) * trending_threshold
float dist_to_choppy = math.abs(flip_frequency - choppy_centroid)
float dist_to_neutral = math.abs(flip_frequency - neutral_centroid)
float dist_to_trending = math.abs(flip_frequency - trending_centroid)
int market_regime = dist_to_choppy < dist_to_neutral and dist_to_choppy < dist_to_trending ? 0 : dist_to_trending < dist_to_choppy and dist_to_trending < dist_to_neutral ? 2 : 1
// ┌────────────────────────────── BOSWaves ─ Adaptive Parameters ────────────────────┐
// └──────────────────────────────────────────────────────────────────────────────────┘
float adaptive_start = use_kmeans ? (market_regime == 0 ? base_start * 0.5 : market_regime == 2 ? base_start * 1.5 : base_start) : base_start
float adaptive_increment = use_kmeans ? (market_regime == 0 ? base_increment * 0.4 : market_regime == 2 ? base_increment * 1.4 : base_increment) : base_increment
float adaptive_max = use_kmeans ? (market_regime == 0 ? base_max * 0.6 : market_regime == 2 ? base_max * 1.3 : base_max) : base_max
if use_kmeans
af := math.min(af, adaptive_max)
// ┌────────────────────────────── BOSWaves ─ KNN Signal Validation ──────────────────┐
// └──────────────────────────────────────────────────────────────────────────────────┘
if use_knn and (raw_bull_flip or raw_bear_flip)
float f1 = bars_since_flip[1] / 50.0
float f2 = last_trend_duration / 50.0
float f3 = af_at_last_flip / base_max
float f4 = flip_frequency / 10.0
float f5 = math.min(ep_progress[1], 5.0) / 5.0
var distances = array.new_float()
var outcomes = array.new_float()
distances.clear()
outcomes.clear()
for i = 10 to knn_lookback
if i < bar_index
bool hist_bull_flip = trend[i] == 1 and trend[i + 1] == -1
bool hist_bear_flip = trend[i] == -1 and trend[i + 1] == 1
if (raw_bull_flip and hist_bull_flip) or (raw_bear_flip and hist_bear_flip)
float h1 = bars_since_flip[i + 1] / 50.0
float h2 = last_trend_duration[i] / 50.0
float h3 = af_at_last_flip[i] / base_max
float h4 = flip_frequency[i] / 10.0
float h5 = math.min(ep_progress[i + 1], 5.0) / 5.0
float dist = math.sqrt(math.pow(f1 - h1, 2) + math.pow(f2 - h2, 2) + math.pow(f3 - h3, 2) + math.pow(f4 - h4, 2) + math.pow(f5 - h5, 2))
float outcome = 0.0
if i > 10
float price_change = (close[i - 5] - close[i]) / close[i]
if raw_bull_flip and hist_bull_flip
outcome := price_change > 0.001 ? 1.0 : 0.0
else if raw_bear_flip and hist_bear_flip
outcome := price_change < -0.001 ? 1.0 : 0.0
distances.push(dist)
outcomes.push(outcome)
int n = distances.size()
if n > 1
for i = 0 to math.min(k_neighbors, n - 1) - 1
int min_idx = i
float min_val = distances.get(i)
for j = i + 1 to n - 1
if distances.get(j) < min_val
min_val := distances.get(j)
min_idx := j
if min_idx != i
float temp_dist = distances.get(i)
float temp_out = outcomes.get(i)
distances.set(i, distances.get(min_idx))
outcomes.set(i, outcomes.get(min_idx))
distances.set(min_idx, temp_dist)
outcomes.set(min_idx, temp_out)
float weighted_success = 0.0
float total_weight = 0.0
int effective_k = math.min(k_neighbors, n)
for i = 0 to effective_k - 1
float dist = distances.get(i)
float weight = dist < 0.0001 ? 100.0 : 1.0 / dist
weighted_success += outcomes.get(i) * weight
total_weight += weight
if total_weight > 0
signal_confidence := (weighted_success / total_weight) * 100
// ┌────────────────────────────── BOSWaves ─ Signal Logic ───────────────────────────┐
// └──────────────────────────────────────────────────────────────────────────────────┘
bool bullish_flip = raw_bull_flip
bool bearish_flip = raw_bear_flip
bool high_conf_bull = bullish_flip and (not use_knn or signal_confidence >= min_confidence)
bool high_conf_bear = bearish_flip and (not use_knn or signal_confidence >= min_confidence)
bool low_conf_bull = bullish_flip and use_knn and signal_confidence < min_confidence
bool low_conf_bear = bearish_flip and use_knn and signal_confidence < min_confidence
// ┌────────────────────────────── BOSWaves ─ Plotting ───────────────────────────────┐
// └──────────────────────────────────────────────────────────────────────────────────┘
color sar_color = trend == 1 ? bull_color : bear_color
plot(display_sar, "Ai", sar_color, style=plot.style_circles, linewidth=2, display=display.none)
p_sar = plot(display_sar, "SAR", color=sar_color, style=plot.style_circles, linewidth=2, display=display.none)
p_price = plot(trend == 1 ? low : high, "Price Anchor", color=color.new(sar_color, 100), display=display.none)
int conf_transp = int(90 - signal_confidence * 0.6)
color conf_color = color.new(sar_color, conf_transp)
//fill(p_sar, p_price,
//trend == 1 ? low : display_sar,
// trend == 1 ? display_sar : high,
// color.new(sar_color, conf_transp + 30),
//conf_color,
//title="Confidence Fill")
// ┌────────────────────────────── BOSWaves ─ Labels ─────────────────────────────────┐
// └──────────────────────────────────────────────────────────────────────────────────┘
// ── Confidence Score Labels ──
if show_confidence_labels and use_knn and (bullish_flip or bearish_flip)
//string conf_text = str.tostring(math.round(signal_confidence)) + "%"
color conf_lbl_color = signal_confidence >= 70 ? #00ff88 : signal_confidence >= 50 ? #ffaa00 : #ff4444
label.new(bar_index, trend == 1 ? display_sar - ta.atr(14) * 0.8 : display_sar + ta.atr(14) * 0.8,
style=label.style_none, textcolor=conf_lbl_color, size=size.normal)
// ── Regime Number Labels ──
if show_regime_labels and bar_index % 2 == 0
string regime_text = str.tostring(3 - market_regime)
color regime_color = color.from_gradient(market_regime + 1, 1, 3, color.new(sar_color, 00), color.new(sar_color, 00))
label.new(bar_index, trend == 1 ? display_sar - ta.atr(14) * 1.5 : display_sar + ta.atr(14) * 1.5, regime_text,
style=label.style_none, textcolor=regime_color, size=size.normal)
// ┌────────────────────────────── BOSWaves ─ Alerts ─────────────────────────────────┐
// └──────────────────────────────────────────────────────────────────────────────────┘
alertcondition(high_conf_bull and barstate.isconfirmed, "ML PSAR Buy", "ML PSAR Buy Signal {{ticker}} {{interval}}")
alertcondition(high_conf_bear and barstate.isconfirmed, "ML PSAR Sell", "ML PSAR Sell Signal {{ticker}} {{interval}}")
alertcondition(bullish_flip and signal_confidence >= 70 and barstate.isconfirmed, "High Confidence Buy", "High confidence ML PSAR Buy {{ticker}} {{interval}}")
alertcondition(bearish_flip and signal_confidence >= 70 and barstate.isconfirmed, "High Confidence Sell", "High confidence ML PSAR Sell {{ticker}} {{interval}}")
alertcondition(market_regime == 0 and market_regime[1] != 0 and barstate.isconfirmed, "Choppy Market", "Entered choppy market regime {{ticker}} {{interval}}")
alertcondition(market_regime == 2 and market_regime[1] != 2 and barstate.isconfirmed, "Trending Market", "Entered trending market regime {{ticker}} {{interval}}")
/////////////
// ┌────────────────────────────── DASHBOARD ──────────────────────────────┐
// ==========================================
var table dash1 = table.new(position.top_center, 2, 3, border_width = 1, border_color = color.new(color.gray, 80))
if barstate.islast
// Panel Bal
table.cell(dash1, 0, 0, "AI @yrk@", text_color=color.white, bgcolor=color.new(color.black, 20), text_size=size.normal, text_halign=text.align_center)
table.merge_cells(dash1, 0, 0, 1, 0)
// AI PSAR Gncel Deeri
table.cell(dash1, 0, 1, "AI:", text_color=color.gray, bgcolor=color.new(color.black, 40), text_halign=text.align_left)
table.cell(dash1, 1, 1, str.tostring(display_sar, format.mintick), text_color=sar_color, bgcolor=color.new(color.black, 40), text_halign=text.align_right)
// Piyasa Vitesi (Rejimi)
string vites_txt = market_regime == 0 ? "TESTERE" : market_regime == 2 ? "TREND" : "NTR"
color vites_col = market_regime == 0 ? color.red : market_regime == 2 ? color.lime : color.yellow
table.cell(dash1, 0, 2, "Sonu:", text_color=color.gray, bgcolor=color.new(color.black, 40), text_halign=text.align_left)
table.cell(dash1, 1, 2, vites_txt, text_color=vites_col, bgcolor=color.new(color.black, 40), text_halign=text.align_right)
Yer mleri