//@version=6
strategy(title="MLPScores", scale=scale.right, overlay=false, calc_on_every_tick=false, initial_capital=1000, margin_long=0, margin_short=0, max_lines_count=500, max_labels_count = 500, default_qty_type=strategy.percent_of_equity, default_qty_value=100, commission_type=strategy.commission.percent, commission_value=0.5, slippage=3, fill_orders_on_standard_ohlc=true)

import TradingView/ta/10
import NiceOrbit/LibraryUtility/18 as utils
import NiceOrbit/LibraryRSIDivergence/2 as rsiDiv
import NiceOrbit/LibraryGaussianChannel/1 as gcl
import NiceOrbit/LibraryMACD/10 as macdLib
import NiceOrbit/LibraryMoneySupply/14 as libMoneySupply
import NiceOrbit/LibraryStochasticDivergence/9 as libStochDiv
import NiceOrbit/LibraryMoneySupplyDivergence/1 as libM3Div
import NiceOrbit/LibraryVWAPDivergence/4 as libVwapDiv
import NiceOrbit/LibraryRealizedPrice/4 as libRealizedPrice
import NiceOrbit/LibraryTradeLogger/8 as tradeLogger
import NiceOrbit/LibraryLongExit/8 as libLongExit
import NiceOrbit/LibraryLongEntry/49 as libLongEntry
import NiceOrbit/LibraryCandlestickPatterns/3 as libCandlePatterns

group_date_range                        = "Back Testing Date Range"
startDate                               = input.time(timestamp("1 December 2017"), "Start", group=group_date_range, inline="date", display=display.none)
endDate                                 = input.time(timestamp("28 February 2026"), "End ", group=group_date_range, inline="date", display=display.none)
timeCondition                           = time >= startDate and time <= endDate

group_neural_activation_thresholds              = "Neural Activation Thresholds"
// ── AUTO-GENERATED MLP PRESETS — do not edit manually ──────────────────────────────────────────
// Run tools/generate_pine_mlp_presets.py to regenerate from trained weight artifacts.
// Last generated: 2026-06-20 20:57  |  5/5 presets found

// ── Preset auto-detection from chart symbol + timeframe ─────────────────────
_tf_secs  = timeframe.in_seconds(timeframe.period)
_tf_label = _tf_secs == 86400 ? "1D" :
             _tf_secs == 14400 ? "4H" :
             _tf_secs == 21600 ? "6H" :
             _tf_secs == 28800 ? "8H" :
             _tf_secs == 43200 ? "12H" : ""

i_preset_override = input.string("", "Force preset (blank = auto)",
    options=["", "COINBASE_BTCUSD 4H", "COINBASE_BTCUSD 6H", "COINBASE_BTCUSD 8H", "COINBASE_BTCUSD 12H", "COINBASE_BTCUSD 1D"],
    group=group_neural_activation_thresholds, display=display.none)

_auto_key = syminfo.prefix + "_" + syminfo.ticker + " " + _tf_label
_preset   = i_preset_override != "" ? i_preset_override : _auto_key
// ─────────────────────────────────────────────────────────────────────────────

float i_long_entry_activation_threshold = switch _preset
    "COINBASE_BTCUSD 4H" => -20.0
    "COINBASE_BTCUSD 6H" => -160.0
    "COINBASE_BTCUSD 8H" => 115.0
    "COINBASE_BTCUSD 12H" => 95.0
    "COINBASE_BTCUSD 1D" => 250.0
    => 95.0  // fallback: COINBASE_BTCUSD 12H

float i_long_exit_activation_threshold = switch _preset
    "COINBASE_BTCUSD 4H" => 30.0
    "COINBASE_BTCUSD 6H" => 140.0
    "COINBASE_BTCUSD 8H" => 200.0
    "COINBASE_BTCUSD 12H" => 250.0
    "COINBASE_BTCUSD 1D" => 160.0
    => 250.0  // fallback: COINBASE_BTCUSD 12H

float i_long_exit_activation_confirmation_threshold = switch _preset
    "COINBASE_BTCUSD 4H" => -230.0
    "COINBASE_BTCUSD 6H" => -270.0
    "COINBASE_BTCUSD 8H" => -160.0
    "COINBASE_BTCUSD 12H" => 10.0
    "COINBASE_BTCUSD 1D" => -120.0
    => 10.0  // fallback: COINBASE_BTCUSD 12H

bool i_use_long_exit_confirmation = switch _preset
    "COINBASE_BTCUSD 4H" => true
    "COINBASE_BTCUSD 6H" => true
    "COINBASE_BTCUSD 8H" => true
    "COINBASE_BTCUSD 12H" => true
    "COINBASE_BTCUSD 1D" => true
    => true  // fallback: COINBASE_BTCUSD 12H

bool i_use_long_entry_confirmation = switch _preset
    "COINBASE_BTCUSD 4H" => false
    "COINBASE_BTCUSD 6H" => false
    "COINBASE_BTCUSD 8H" => false
    "COINBASE_BTCUSD 12H" => false
    "COINBASE_BTCUSD 1D" => false
    => false  // fallback: COINBASE_BTCUSD 12H

float i_trailing_stop_threshold = switch _preset
    "COINBASE_BTCUSD 4H" => 15.0
    "COINBASE_BTCUSD 6H" => 20.0
    "COINBASE_BTCUSD 8H" => 45.0
    "COINBASE_BTCUSD 12H" => 20.0
    "COINBASE_BTCUSD 1D" => 0.0
    => 20.0  // fallback: COINBASE_BTCUSD 12H

int i_regime_window = switch _preset
    "COINBASE_BTCUSD 4H" => 0
    "COINBASE_BTCUSD 6H" => 0
    "COINBASE_BTCUSD 8H" => 0
    "COINBASE_BTCUSD 12H" => 0
    "COINBASE_BTCUSD 1D" => 0
    => 0  // fallback: COINBASE_BTCUSD 12H

float i_regime_entry_min_score = switch _preset
    "COINBASE_BTCUSD 4H" => -1000.0
    "COINBASE_BTCUSD 6H" => -1000.0
    "COINBASE_BTCUSD 8H" => -1000.0
    "COINBASE_BTCUSD 12H" => -1000.0
    "COINBASE_BTCUSD 1D" => -1000.0
    => -1000.0  // fallback: COINBASE_BTCUSD 12H

bool i_mvrv_suppress_bear = switch _preset
    "COINBASE_BTCUSD 4H" => false
    "COINBASE_BTCUSD 6H" => false
    "COINBASE_BTCUSD 8H" => false
    "COINBASE_BTCUSD 12H" => false
    "COINBASE_BTCUSD 1D" => false
    => false  // fallback: COINBASE_BTCUSD 12H

int i_exit_score_window = switch _preset
    "COINBASE_BTCUSD 4H" => 2
    "COINBASE_BTCUSD 6H" => 1
    "COINBASE_BTCUSD 8H" => 1
    "COINBASE_BTCUSD 12H" => 1
    "COINBASE_BTCUSD 1D" => 4
    => 1  // fallback: COINBASE_BTCUSD 12H

int i_entry_score_window = switch _preset
    "COINBASE_BTCUSD 4H" => 1
    "COINBASE_BTCUSD 6H" => 1
    "COINBASE_BTCUSD 8H" => 1
    "COINBASE_BTCUSD 12H" => 1
    "COINBASE_BTCUSD 1D" => 1
    => 1  // fallback: COINBASE_BTCUSD 12H

// MLP weight arrays (populated on barstate.isfirst from the preset block below)
// Architecture: 55 → 16 → 8 → 1
var float[] _w1 = array.new_float(880, 0.0)  // W1 [16×55]
var float[] _b1 = array.new_float(16, 0.0)
var float[] _w2 = array.new_float(128, 0.0)  // W2 [8×16]
var float[] _b2 = array.new_float(8, 0.0)
var float[] _w3 = array.new_float(8, 0.0)  // W3 [1×8]
var float[] _b3 = array.new_float(1, 0.0)

// COINBASE_BTCUSD 4H  arch: [55, 16, 8, 1]  artifact: 2c4f2cdb
_fw_COINBASE_BTCUSD_4H_w1() =>
    float[] _tw = array.from(0.02396222206, 0.3796166477, 0.3080250873, 0.04055320796, -0.2638379287, -0.02857502032, -0.08210590119, -0.07633062142, 0.36789094, -0.2613704543, 0.1014915798, 0.2433746461, -0.1600120393, 0.2937375065, -0.1371152814, 0.2229890669, -0.02797980375, 0.07129294286, -0.3612789635, 0.2290610139, 0.4162650051, -0.05472851378, 0.3237742501, 0.06954646027, -0.1553422991, 0.04020640786, 0.1226995668, -0.2882058917, 0.01854753816, 0.01351007926, 0.01838971221, 0.01971364732, -0.08444795699, 0.1014506685, 0.04943917138, 0.1186919631, 0.1150054762, -0.089691257, -0.3687418941, -0.2542180334, -0.2542950402, 0.108431202, 0.523151753, -0.04670447589, -0.065121057, 0.1463078941, 0.188294047, -0.1870856735, 0.4742580814, 0.01019782598, 0.09384516845, 0.2852453019, 0.156323771, 0.1752243019, -0.1254496334)
    float[] _tr = array.from(0.1818617924, 0.1008210587, -0.2532854557, 0.3591363882, 0.009834566314, -0.007902647412, 0.3901043443, -0.003008029875, 0.009915452019, -0.1628525515, 0.3679892872, -0.00502277366, -0.1617816213, 0.3447697929, -0.003289584139, -0.2144313255, 0.04551640703, -0.1280784197, -0.1233537412, -0.2246365361, 0.2187735473, 0.09816449378, -0.2932530694, -0.1462072827, -0.07422582527, 0.1807638447, 0.191713235, 0.1057505205, 0.2354744432, -0.2660434558, -0.2234693103, 0.4325991238, -0.02752009319, 0.09238234374, -0.03538126482, 0.2880023023, 0.3379813096, -0.2851448995, -0.1940350076, 0.4089802189, -0.02116582083, 0.1747314009, 0.2552765954, -0.3699069578, -0.3559250164, -0.2696967562, 0.1341781594, -0.05024103882, -0.0003785680803, -0.2840948699, -0.1064418346, 0.0563437125, -0.01389987073, 0.1332788827, -0.1536183411)
    array.concat(_tw, _tr)
    _tr := array.from(-0.1271082072, -0.03898976852, 0.08597996985, 0.3057952309, 0.1491178171, 0.1936503072, 0.1017383094, 0.05928491216, -0.4668241145, -0.5722770547, 0.1048089101, -0.1202191345, 0.02173817659, 0.2896085799, -0.0234837208, -0.06760934339, -0.1488952449, -0.3494623249, -0.009376240392, -0.0822161132, 0.113145752, 0.1778589074, 0.145310355, 0.03210427486, 0.2510027106, -0.1274231943, 0.08571329407, 0.2567418354, 0.400527125, -0.02159337137, -0.2078575774, -0.0524104128, -0.04061402447, 0.1249253336, 0.04339181745, 0.1884612596, -0.06041472303, -0.277584774, -0.3144157887, 0.074211599, 0.1114822459, -0.2676422124, 0.07227481434, 0.07063106044, -0.4419009366, 0.2407094559, -0.02180105911, -0.06380596144, -0.1704050295, 0.2779389841, 0.2011995392, -0.2312196604, 0.3164552207, 0.1724529006, 0.1244443823)
    array.concat(_tw, _tr)
    _tr := array.from(0.06103211502, -0.1584795864, -0.1671493883, -0.0457906902, -0.3669759831, 0.2420784455, 0.2542525102, -0.2507048977, -0.1638702252, -0.2478229603, -0.2301350165, 0.1850459627, -0.1550246279, -0.1523422675, -0.1708918573, 0.1970885094, -0.1764394634, -0.1738269121, -0.2233906762, -0.1682835073, -0.1312906335, 0.3629513317, -0.1543164932, 0.0406285737, 0.150397089, -0.1115201193, -0.1109946636, 0.05553641466, -0.05316818548, 0.2349028228, -0.03888248878, -0.3429477912, -0.07556755267, 0.14064971, 0.3337786254, -0.08784895011, -0.3606772537, -0.02216907791, -0.1150482592, 0.1103291624, 0.08700329537, 0.2061765129, -0.2282181731, -0.1006387501, 0.01958317425, -0.2441489532, -0.352285039, 0.1240339914, 0.2094464044, -0.2933216404, 0.1848707387, -0.09725423495, -0.2857593523, 0.06533605791, 0.2789452458)
    array.concat(_tw, _tr)
    _tr := array.from(-0.07938433701, -0.3831004503, 0.1815903482, 0.1698568499, -0.2006117163, 0.3289641569, 0.1807172174, -0.2303541902, 0.2285512319, 0.04224385778, 0.05519431545, -0.3387759953, 0.02832495639, -0.038458608, -0.001404824983, 0.06041228536, 0.244179089, -0.07145838108, 0.0720582877, 0.1877135065, 0.2439021961, 0.1335615868, 0.1242451116, 0.2131766845, -0.1105751582, -0.1543534439, 0.07810328928, 0.1601667303, -0.1581667945, -0.02288137662, 0.3190978291, 0.09840927061, -0.5509785095, -0.1406153635, -0.493242612, -0.06305627429, 0.2374910678, 0.01034723646, 0.05277786419, 0.1832243861, 0.1580533009, 0.2833926778, -0.09570587504, 0.02278152719, -0.2331838783, 0.01382521065, -0.347520785, 0.180333551, 0.1333081325, -0.351464807, -0.1714790683, -0.008886278705, -0.09063623134, 0.1189316459, -0.04204392858)
    array.concat(_tw, _tr)
    _tr := array.from(-0.2116909883, 0.009235660461, 0.03709884031, -0.235629893, 0.1119451056, -0.4317446677, 0.2617184923, 0.1562040093, -0.10419948, 0.3280815817, -0.0791253562, 0.1616034554, 0.0350430749, -0.1550230534, 0.03782225273, -0.1293494447, -0.0575340604, 0.2092756198, -0.02258816059, 0.04486671817, -0.05794004778, -0.1657766021, -0.1655187251, 0.2185989982, 0.143535238, -0.3458278166, -0.1481458378, 0.2076658571, -0.303580001, 0.02542172594, -0.5247000844, 0.06497292096, 0.1206916908, -0.1551685717, 0.02995677232, -0.2034280594, -0.03211114906, 0.2891439668, 0.0652773533, -0.1894170308, -0.2334772235, 0.6393993108, -0.2139161084, -0.2606301995, -0.131118378, 0.09792403297, -0.2030934126, -0.008183174616, 0.05707828713, 0.1068918163, 0.3361449528, 0.08558367678, 0.2656584741, -0.29114657, -0.09486186772)
    array.concat(_tw, _tr)
    _tr := array.from(-0.1412502181, 0.1461021105, -0.02358274762, -0.04334626557, -0.124218953, 0.08896116001, 0.2535871911, -0.4500523533, -0.2941980371, 0.08243822422, -0.2477671626, -0.1262589523, 0.1398982554, -0.303494852, 0.09204946149, 0.4186636346, -0.0362011735, -0.03479288757, -0.4282789789, 0.1851982428, -0.3038198733, -0.04145637958, -0.1459951571, -0.2251942161, 0.1117135424, 0.3374224907, 0.06771735042, -0.09705371063, -0.1915582406, 0.2506635686, -0.09881697514, 0.2933372556, 0.09666816795, 0.09874609194, -0.08650079182, 0.03973216496, -0.06849612031, -0.09955707519, -0.1540546071, 0.3971812642, 0.1256748488, 0.176971658, -0.09404265588, -0.2494134825, 0.3847186482, 0.1037192484, 0.1611922296, 0.545586131, -0.1289319207, -0.07388944837, -0.3712608502, -0.08266345952, 0.01194489655, -0.04598245487, -0.1378458852)
    array.concat(_tw, _tr)
    _tr := array.from(-0.1325240346, -0.2556450058, 0.2389324375, -0.3849234636, -0.1343213377, 0.04677669548, 0.1919358858, -0.1654801585, 0.009291408567, -0.03783829829, 0.06933928684, -0.4555283443, 0.3758561833, -0.5296278036, -0.1603115284, 0.2448224902, 0.1958515864, 0.01349613382, -0.06294995909, 0.02588512265, -0.02593789645, 0.04008558266, -0.1410114162, 0.0994386428, 0.1218861681, -0.3362246117, -0.1044318635, -0.2107600775, 0.03850470796, -0.03458246866, 0.117604547, 0.2634262219, -0.1085456987, -0.05871869117, -0.2496884248, 0.2245259739, 0.2036021816, 0.2743407983, 0.348084904, -0.02376795504, -0.09941061114, 0.02945319877, 0.06067163347, 0.06863342579, -0.3487531557, 0.02694000535, 0.3524603088, -0.2154167801, -0.3178198738, -0.1285655916, 0.03585838897, -0.1850542072, -0.3135607673, -0.2506027202, -0.3738092433)
    array.concat(_tw, _tr)
    _tr := array.from(-0.3016936726, -0.09742209311, -0.009550283084, -0.0594999366, 0.06140451335, -0.568389407, 0.1559718624, 0.05113081776, 0.2361555093, 0.3405095401, -0.168544844, -0.09737360628, -0.3922325468, 0.07067203872, 0.1073959026, 0.1539227519, 0.1052182723, 0.23580159, 0.0004716250206, -0.2336395152, 0.2627268147, -0.1116526624, 0.1296741545, -0.1285154072, 0.158525952, 0.001473936968, -0.2873979651, 0.06420400631, 0.1784102844, 0.3743769983, -0.2249557887, -0.0683037698, 0.1049167824, 0.03842034165, -0.3146934949, 0.1648593958, 0.1763193818, -0.4552003613, 0.4671403954, 0.3090929677, 0.2545045659, 0.3094063045, -0.0395236174, -0.2465562733, 0.05597471856, -0.3522427843, -0.02174412289, -0.5458916326, 0.3679845916, -0.2459544784, -0.1711006336, -0.1146001309, -0.08012327136, 0.2112276563, 0.2994928836)
    array.concat(_tw, _tr)
    _tr := array.from(-0.1269339847, 0.1178884789, -0.2544375085, -0.1143394793, 0.163021164, -0.05670773026, 0.6931730849, 0.1561706054, -0.3703604615, -0.02744092827, 0.06671344915, -0.05906122952, -0.3516993215, -0.03257354846, -0.248486288, 0.3868884595, -0.4008255112, -0.07124432205, 0.3098048685, 0.1083909171, -0.4082557406, 0.2238204951, 0.04753846689, -0.4985114478, 0.08216625746, 0.02272980161, 0.04391771074, 0.2965195841, -0.2995114324, 0.2927351556, 0.1869069081, -0.1924434576, 0.4664266078, 0.2095238597, -0.03634384494, -0.04702084965, -0.09209170608, 0.4899620183, 0.3283722348, 0.02714271846, -0.136575587, -0.3376992981, 0.1672720722, -0.2850369507, 0.2086972019, 0.332847247, 0.2617555146, -0.1128866846, -0.04283174264, 0.5187973451, -0.2306266215, 0.2870337522, -0.08528499104, 0.1885489306, 0.006657388456)
    array.concat(_tw, _tr)
    _tr := array.from(-0.2697057733, 0.09675731558, 0.1913745528, -0.3632764614, 0.258613017, -0.4268579271, -0.311021092, 0.07722798994, -0.05553867214, 0.01651058105, -0.2009134171, 0.5226491564, 0.1586797242, 0.2009600866, -0.02040620604, 0.3248149336, -0.2650793426, -0.1033425362, 0.07457788535, 0.2176499808, -0.1249278108, -0.1651734695, 0.07930388241, 0.1564668098, -0.1847019965, -0.2636453105, -0.1058389391, 0.03964109054, 0.01086853733, -0.07428905416, -0.06414305025, -0.1084781002, 0.129499864, -0.3255986248, -0.1356978089, -0.04232293329, 0.1816452427, -0.1630137412, -0.002687083832, -0.7473483354, 0.0589075312, 0.08685322029, -0.06463066717, 0.208327752, 0.02690633976, -0.1771245776, 0.09493078714, 0.01505294073, 0.09284949411, -0.1468573318, 0.2438540417, -0.3635738983, -0.02960706747, 0.09125236073, -0.04339972739)
    array.concat(_tw, _tr)
    _tr := array.from(0.1064206858, -0.05819538447, 0.166384171, 0.2020277728, 0.21436638, 0.03637093379, 0.2149238404, -0.08314255404, -0.01105668314, 0.1455039375, 0.04996177206, -0.03346190156, -0.09702129807, 0.1125867196, 0.4077207773, -0.1468670949, 0.01936014006, 0.02947328434, 0.1536781162, -0.3161779467, -0.2378445027, 0.4737738082, 0.268985113, -0.2952397111, -0.2499364462, -0.06560041916, 0.4120303664, 0.1213008093, 0.06186413822, -0.3319812603, 0.0409250302, 0.06020805616, 0.2750575207, -0.3345236051, -0.3506412323, -0.1572840873, -0.5518521083, 0.06104250407, -0.05310548716, -0.3035943273, -0.1213536412, 0.511905751, 0.504826437, 0.202408116, 0.3709905622, -0.04363196506, 0.03861851915, 0.1693347492, -0.127428628, -0.1137740109, -0.3973120506, 0.3153546333, 0.2264071307, 0.06788833239, -0.1530718299)
    array.concat(_tw, _tr)
    _tr := array.from(-0.1145129772, 0.1051038213, -0.09932920389, -0.4483374648, -0.1643018229, -0.03188536642, -0.2558586078, 0.3152385645, 0.05354359865, 0.07673970714, 0.1000659859, 0.03278128287, 0.02067373563, 0.07338321802, 0.2449983009, -0.1598486499, 0.09137590448, 0.03149574477, 0.04384443897, 0.258589775, 0.1788085851, -0.02995982995, 0.1636495034, 0.1245801847, 0.0005515842689, -0.03472723374, -0.1225564493, 0.5378674711, 0.2748218774, 0.1369222292, -0.1840963206, -0.2513958555, 0.2627480611, 0.2568690568, 0.1743170161, 0.06227033838, 0.06824651389, 0.1454636056, 0.09589887882, 0.2245707907, 0.1301261765, -0.350986963, -0.2882350268, 0.4603048706, -0.1205399348, 0.1554069296, -0.4275505174, -0.02819036854, 0.1100152606, 0.3227018469, 0.1504381395, -0.3731506909, 0.2832678231, -0.1785303406, 0.1373068506)
    array.concat(_tw, _tr)
    _tr := array.from(-0.1118998689, -0.120599415, 0.09642620795, -0.2068326441, -0.1320847467, 0.1888832578, -0.1329018494, 0.1405179613, -0.1858767126, 0.1992569771, 0.1342303828, 0.1500559124, -0.6079165202, -0.06289191754, 0.0837221334, 0.1669858421, -0.05139726877, 0.04041684898, 0.3379529149, 0.2693348036, -0.1729686429, -0.1698689846, 0.2771237677, 0.1565295048, -0.1470122817, 0.3633740175, -0.06259789479, 0.2259017528, -0.05018505508, 0.2221906171, -0.007872802875, -0.1168020623, 0.1007797559, 0.4835611403, -0.4391898935, -0.3034064582, -0.3145522637, 0.1074114345, -0.4354059728, -0.4776849905, -0.131037499, 0.1868902172, -0.0038091806, 0.007193721149, -0.2446862349, 0.2634098437, -0.2179620584, 0.2513663279, -0.2348889475, 0.1316655699, -0.004053468564, -0.2876893676, 0.1250563608, 0.1029203338, 0.0673431592)
    array.concat(_tw, _tr)
    _tr := array.from(-0.152316905, -0.1557914244, 0.4397619352, 0.07844870159, -0.0003345878702, -0.07962528452, -0.1615299281, 0.003052078778, -0.1988267532, 0.03436039381, 0.02422413418, 0.2671583508, 0.01692023121, -0.2120499455, -0.1397411637, -0.1135697198, 0.03293046326, -0.1526537822, -0.1068353463, 0.04213446535, 0.1819620512, 0.1606770275, -0.09577289372, -0.03139008941, -0.1362275135, -0.09219038905, 0.06403254836, 0.08559416469, -0.1441853873, -0.4518695586, 0.04837388414, 0.1861717238, 0.424847444, 0.3448253798, 0.1535271406, 0.4416194288, -0.02905172183, 0.1438757042, -0.2288356853, -0.1523014919, 0.08525715638, -0.1337167016, -0.03022815772, 0.2084816786, -0.1900333117, -0.2104562781, 0.1832430658, -0.1387698648, 0.09428287798, 0.3095829061, -0.2152073269, -0.175094653, 0.06375602392, -0.1259949858, 0.3375589019)
    array.concat(_tw, _tr)
    _tr := array.from(0.0001749108224, 0.03525887104, -0.3190483576, 0.2267304841, 0.1160536926, 0.1285047158, -0.001803606723, -0.5360431116, -0.1739882671, -0.2807714795, 0.07944848043, 0.0916013328, 0.07768533145, -0.2306674208, -0.1748501807, 0.09935714635, -0.4112910822, -0.09434794348, 0.2029057508, 0.2558507591, -0.1942070026, -0.03248599395, 0.05568823133, 0.4349650326, 0.09909262802, -0.02047262092, 0.4098965181, 0.05438607122, 0.2863625332, 0.2467856727, -0.2137411264, -0.03489060075, -0.0838589938, -0.2711424001, 0.04342828709, 0.06273233733, 0.08570722423, 0.1349758048, 0.01352498542, 0.1362592708, -0.01410919753, 0.1263038966, 0.5031056508, -0.4133992295, 0.2464039415, -0.0861267371, 0.04711263015, -0.1986468855, -0.337573765, -0.25006348, -0.3741883794, 0.395759819, 0.005920722663, -0.3970936532, -0.2386019804)
    array.concat(_tw, _tr)
    _tw

_fw_COINBASE_BTCUSD_4H_b1() =>
    array.from(-0.02954074885, 0.1872792154, -0.07113038894, 0.3069506245, 0.3894421842, 0.2986676259, 0.2756688573, 0.129743883, 0.03326077467, -0.05274847593, -0.1937479104, -0.05738383585, 0.05590773135, 0.1393502865, 0.2165692686, 0.3595211099)

_fw_COINBASE_BTCUSD_4H_w2() =>
    float[] _tw = array.from(-0.007479070302, 0.5609269937, -0.1008510836, -0.1877834062, -0.02301426902, 0.4763805467, -0.1106214037, 0.2725863203, -0.1053933621, -0.2055598494, 0.04655034702, -0.2432773323, -0.06870092765, 0.1736038564, -0.01848214658, -0.03570258671)
    float[] _tr = array.from(-0.06319096256, -0.07293213174, -0.0891150941, 0.7492261592, 0.3104528652, -0.112795903, 0.1960300392, -0.02870363364, -0.01817068214, -0.2747966603, -0.7642773513, -0.1151210736, -0.2627117455, -0.1689239304, -0.2904108248, -0.1904040365)
    array.concat(_tw, _tr)
    _tr := array.from(0.3429894272, -0.443847236, 0.3731502575, -0.1757362872, -0.3440804633, 0.2461366763, -0.04010877498, -0.1774677499, -0.07655597382, -0.5255125802, 0.01999875489, 0.2831924261, 0.1136418669, 0.1144155293, -0.04927062938, 0.4607931353)
    array.concat(_tw, _tr)
    _tr := array.from(0.01566665692, 0.1464507771, 0.05509919868, -0.02141252357, -0.03873859409, 0.1333744796, 0.08247130481, 0.1743629727, 0.2378081679, -0.02790185511, 0.2286834019, -0.299371088, 0.1751584252, -0.1079357717, -0.2542440811, 0.3296136371)
    array.concat(_tw, _tr)
    _tr := array.from(-0.1866572418, -0.0296152601, 0.008136360896, 0.2457448722, -0.1241033789, 0.1213044361, -0.0662000842, -0.1060692299, 0.008135286977, -0.02625035022, -0.1509285423, -0.342723739, 0.2350115637, 0.3316001831, -0.2232283454, 0.2055281321)
    array.concat(_tw, _tr)
    _tr := array.from(-0.06255291691, -0.172033478, -0.4091909437, 0.09119859884, 0.4065957232, 0.2107115659, 0.007920678799, 0.03174520751, -0.2850366614, 0.1431950403, 0.1047949614, 0.2315910383, 0.1680600682, -0.2636017179, -0.1753012539, 0.05989142854)
    array.concat(_tw, _tr)
    _tr := array.from(0.03949273844, -0.4279643894, -0.1606779449, -0.1874222328, -0.1360276798, -0.2089750667, 0.3472700781, 0.2154611066, 0.05275821305, -0.01615090658, -0.09197968312, -0.2403102952, 0.3235979, 0.3626692257, -0.06446484661, -0.06820968665)
    array.concat(_tw, _tr)
    _tr := array.from(-0.005908167655, -0.09901089968, 0.1124990495, 0.1007080119, -0.3307456121, -0.2687069198, -0.1243653348, 0.2072084483, 0.1275143341, -0.08350145581, 0.007085495935, 0.1681829085, -0.4938946374, 0.1138729916, 0.003865473829, -0.0787639331)
    array.concat(_tw, _tr)
    _tw

_fw_COINBASE_BTCUSD_4H_b2() =>
    array.from(0.1094717338, 0.2854793414, 0.05686791816, -0.2137384153, -0.2577470514, -0.1142010138, 0.204378508, -0.03363615182)

_fw_COINBASE_BTCUSD_4H_w3() =>
    array.from(-0.8714082685, -0.560799833, -0.5001271217, -0.1235430947, 0.08264020173, 0.3925550573, -0.3045073746, 0.4029017626)

_fw_COINBASE_BTCUSD_4H_b3() =>
    array.from(-0.4342421992)

// COINBASE_BTCUSD 8H  arch: [55, 16, 8, 1]  artifact: 8523f5f3
_fw_COINBASE_BTCUSD_8H_w1() =>
    float[] _tw = array.from(-0.1839898501, 0.08001880791, 0.08345392452, 0.1908108101, -0.285553911, 0.1885380561, -0.3425458735, 0.04154723049, 0.04135676582, 0.0463336992, -0.1962356409, 0.1053858144, 0.1671602134, 0.2557058555, -0.03869606056, -0.03013799186, 0.03191706068, 0.1328680198, 0.4604306195, 0.08064549291, 0.5007800193, 0.1026807157, -0.04973625303, 0.2337520665, -0.1323826977, 0.131784936, -0.2042538305, -0.2662480227, -0.2534870675, -0.4811243215, 0.1744142478, 0.1701255282, -0.2816106696, 0.1397709292, -0.01255737961, -0.1138660575, -0.2174823588, 0.0261626511, -0.4925578101, 0.3488368613, -0.4758105677, 0.01598383883, -0.1542805812, -0.1013355154, 0.08616112697, 0.05537274347, -0.4427491739, -0.2855116035, 0.3629786962, 0.3296666603, 0.07699941369, -0.1490792825, -0.05088902527, 0.01330518084, 0.1769172594)
    float[] _tr = array.from(-0.081639523, 0.1545829376, -0.1796194751, -0.2335837408, 0.702241309, 0.1417697712, 0.04853127959, -0.1947395588, -0.00424650831, -0.2811147682, 0.04734908636, 0.2555561461, 0.01406775665, 0.5571849403, 0.3018165472, -0.0123777206, -0.2153580659, 0.2078163073, 0.5584436828, -0.3410225283, -0.02348627128, -0.4044755301, 0.33349357, 0.07355596834, 0.2356117819, 0.1131753507, 0.1212945436, -0.05971497009, 0.004637603103, 0.2547288494, -0.003864754477, -0.536700673, 0.1669189951, 0.4687394066, -0.0796481341, -0.3196452565, 0.397323838, -0.4553053008, -0.2166517533, -0.4730610596, -0.2080762363, 0.08427747656, 0.1863193715, -0.09760163771, -0.475275589, -0.1809857209, 0.1191502858, -0.2504217095, 0.2097401192, -0.2564011533, -0.2027272555, 0.02315073538, 0.009790394273, -0.3213176245, 0.2570219133)
    array.concat(_tw, _tr)
    _tr := array.from(0.120691431, 0.2391317712, -0.1957193896, 0.402390439, 0.2940829053, 0.430286824, -0.01752327411, -0.05051161644, -0.1510723533, -0.1788692206, -0.06289825055, 0.2117305459, -0.2109636744, 0.01598256682, -0.06041955186, -0.1558219036, -0.1972057772, -0.07825293142, -0.04887631622, 0.2887818888, 0.4006304621, -0.04599064478, -0.1033044301, 0.1022637034, -0.1159939446, -0.3362755163, 0.1187113458, 0.03236575579, -0.5097208445, -0.3345700662, 0.09332280743, -0.2459906634, -0.2510629589, -0.07520880945, -0.3264091624, -0.09744077675, -0.2972144599, -0.344542824, -0.2608160706, -0.1996434196, 0.4826506326, -0.1650249635, 0.4200279636, -0.1191339411, -0.541741102, 0.04029615825, 0.1011785891, 0.2626626711, 0.01294391916, -0.01192283917, 0.2241330987, -0.1191692855, 0.1725178029, -0.09008098328, 0.2850360353)
    array.concat(_tw, _tr)
    _tr := array.from(0.7267003537, -0.1180874276, 0.4233242157, -0.255064653, 0.05690559268, 0.2025140321, 0.2259731874, 0.2380614234, -0.1213751065, 0.08259681685, -0.1117460687, -0.1628951854, 0.07625536541, -0.1989788777, 0.1012214727, 0.3422870593, 0.2587686979, -0.3459350853, 0.552638684, 0.2112078773, 0.1796946724, 0.3296127553, -0.2852107324, -0.0743991664, -0.03526279882, -0.5868484959, -0.2066430505, -0.2544707577, -0.02386437652, 0.4445895819, 0.3559084939, -0.26972383, -0.1504294661, 0.03798521022, 0.1381922844, -0.1856147137, -0.208376037, 0.07416553039, 0.3329549867, 0.3282995949, 0.2075410336, 0.4394898409, 0.1089102203, -0.3280697223, 0.2825902531, -0.2295521746, -0.02677723912, 0.6374805785, 0.4309417304, -0.2136883605, 0.03721713942, 0.2916186325, 0.2683505321, -0.02441361403, 0.01648136931)
    array.concat(_tw, _tr)
    _tr := array.from(0.1547494174, -0.03733031415, 0.01664965689, 0.1389243312, -0.4446543993, 0.01627354845, 0.2469967022, 0.2620702527, 0.009367608133, 0.01742964169, -0.1954455307, 0.07881966023, 0.2325965788, -0.08092979457, -0.2699525352, 0.2189616928, 0.01635018863, 0.3841037264, 0.1505872576, 0.2918583373, 0.2809089827, 0.3117788549, 0.3781840225, 0.1570362892, -0.3468981168, -0.1467964461, -0.005664630907, -0.2074011863, -0.2664508794, -0.05638986348, 0.164182534, -0.10067182, 0.04153654011, 0.1463195886, 0.2214110356, -0.3668824072, 0.239680249, 0.1701191143, -0.3533397511, -0.009911851901, 0.1710612693, -0.06829312845, -0.02797176048, 0.27166705, 0.2609465058, 0.3572593756, 0.2520158721, -0.3352267949, -0.3071451462, -0.09199939258, -0.04695135105, -0.005931443476, -0.3269493391, 0.4793137142, 0.3172104066)
    array.concat(_tw, _tr)
    _tr := array.from(-0.07091608472, -0.1792668986, 0.2138746381, -0.1558232034, -0.1403776971, 0.08450978561, -0.1623114513, 0.01453490107, 0.111698011, -0.1049912826, 0.09629417693, 0.04605991249, 0.2521696292, -0.140108364, 0.2083970645, -0.09635903812, 0.277764437, 0.2199710475, 0.04790119676, -0.3200264396, -0.04682877109, 0.1387465755, -0.3004601758, -0.02704185979, -0.003648040108, 0.1237353475, -0.4779522074, 0.01324407512, -0.3092082234, 0.1373173127, 0.2633712549, 0.07031001656, 0.124301844, 0.2731448799, -0.0118185093, -0.1151171036, -0.05829935951, 0.2445951264, -0.4034904627, -0.2344178063, 0.126592271, -0.331542235, -0.08912061714, -0.2642710019, -0.1701806442, 0.09677681529, -0.2992404053, 0.005491893404, -0.1474986679, 0.2373292662, 0.4360760585, -0.05849508338, 0.6408489514, -0.4998750934, -0.223107671)
    array.concat(_tw, _tr)
    _tr := array.from(0.1335598284, -0.09864361706, -0.4382821432, -0.01389546562, -0.1465713701, 0.05649236122, -0.2630277213, -0.1215475747, 0.002701331907, 0.2099935309, -0.04813349026, -0.01627907481, 0.09529472594, -0.07856718691, -0.1871636835, 0.4385647889, 0.07206530753, 0.08419467787, 0.03615137454, 0.3174292692, -0.06406616258, 0.2418315416, 0.301337432, 0.2708543007, -0.3578286773, 0.003004276478, -0.6299609289, 0.04872367567, 0.1853103367, 0.4748028561, 0.5691146386, -0.01090490991, 0.2442894223, 0.003768497438, -0.03530378272, 0.3073893631, 0.06978031628, -0.08482833077, -0.001562684651, 0.1447458656, 0.1156061793, 0.1161305656, -0.07215235479, 0.1469204236, 0.03053015346, -0.02862487161, -0.05941077963, -0.01108189194, 0.2057012944, 0.2740045146, -0.2055820982, 0.007052380185, 0.1556364663, 0.1869741027, -0.1321150988)
    array.concat(_tw, _tr)
    _tr := array.from(0.05078802651, 0.1788603431, -0.5691569524, -0.0645437589, -0.008473904274, -0.01273875636, -0.4640333072, -0.1494943435, 0.3986979923, -0.1587282711, 0.3858432436, -0.0144597403, -0.1165169573, -0.04703975293, -0.08919712308, 0.5390318164, 0.4126612433, -0.1485060559, 0.04273632061, 0.4009080162, 0.09456791797, -0.003980398057, -0.4045604894, 0.06259799831, -0.1773629736, -0.3184822659, -0.317522353, 0.03313463655, -0.08560154056, -0.1789534002, -0.2026017913, -0.1223494625, -0.2297247651, 0.01137792692, -0.391719224, -0.02132495933, 0.006819540229, 0.2466412048, 0.1992593765, 0.002647919172, -0.2757619194, 0.4961686705, -0.1975292863, -0.09306399801, -0.02996999876, 0.2082001044, -0.3366140456, 0.1226676256, 0.2500547802, -0.2936805044, -0.3832897411, 0.01369172518, 0.1579234445, -0.3473185262, 0.2380662868)
    array.concat(_tw, _tr)
    _tr := array.from(0.05465580368, -0.09315625177, 0.3436469957, -0.07373525851, 0.1813876377, 0.1363645993, -0.1961050455, 0.1007654517, 0.0779663191, 0.003801054825, 0.02911328083, 0.05534358285, -0.2047494244, -0.05287224465, -0.5884138054, -0.1134053928, 0.1976363773, 0.3824634278, -0.1233721999, -0.0006388921945, 0.08828338485, -0.1415172949, 0.3035621523, -0.0814523017, -0.2297983627, -0.137516009, 0.4669000166, 0.4283839841, 0.09162861473, -0.02523232712, 0.2516969132, -0.207227466, -0.01425639171, -0.2580511629, -0.3166439396, 0.1000618989, -0.3089210731, -0.03625886289, -0.2561834857, -0.2658658961, -0.08510092306, -0.04531289917, 0.1798775196, -0.08384643409, -0.08528153352, -0.1514293303, 0.5274616788, -0.1136567929, -0.004013283457, -0.2320084882, 0.07789568202, 0.02001394328, -0.1140114827, -0.09720546454, 0.2198038075)
    array.concat(_tw, _tr)
    _tr := array.from(0.2572633021, 0.1388582279, -0.06081290597, -0.1803782351, -0.02614058806, 0.2540513914, 0.2249807966, 0.3595121212, -0.1662495186, 0.1412450366, 0.1319910399, -0.1644655849, -0.2578162175, -0.138461494, -0.1094032017, -0.2827940858, 0.1545261037, -0.06496161154, 0.3551905552, -0.2086509591, 0.1867811213, 0.2824738375, 0.2683039321, 0.2119978369, 0.1933202876, -0.2095524404, 0.4948908792, 0.3893930875, 0.0925926738, 0.3203070343, 0.1586574985, -0.4801037812, 0.1561530287, 0.3067372867, -0.0007372072504, -0.3428011567, 0.2383629232, 0.4499319889, -0.2173292798, -0.567893172, 0.0605892296, -0.1023270352, 0.3653730518, 0.3298263617, 0.08214479934, 0.1202707272, 0.2200341817, 0.0009789809662, 0.361858453, 0.3528267212, -0.2059000973, 0.4850632529, 0.2028724974, 0.09176349407, 0.2635160194)
    array.concat(_tw, _tr)
    _tr := array.from(0.1854631886, 0.1306264593, 0.6479520627, -0.3935496652, 0.2559107708, -0.2826333769, -0.07876034437, 0.02363553916, -0.2714025495, -0.05018907624, -0.5313016589, -0.00777573541, 0.214488141, -0.2240980038, 0.1109599384, -0.4387182579, -0.3046623359, 0.4738942009, -0.08720573994, 0.2259888952, 0.1395088317, 0.02208767863, 0.1640540417, 0.2200326855, 0.2093898672, -0.1547389559, -0.1833037963, -0.03655629476, -0.290168692, -0.07924862183, 0.2839679491, -0.5243175282, -0.009734628593, -0.158324197, -0.4012782636, -0.06299343989, 0.1241504652, -0.1321693452, -0.02337186311, -0.2848842295, 0.1275117638, 0.04152523977, 0.1486259925, 0.145820964, -0.1793687855, 0.135190404, -0.1525401791, -0.3816486629, -0.07163135157, 0.5349467003, -0.09286572767, -0.3117789168, -0.08964037496, 0.001167747132, 0.2660166937)
    array.concat(_tw, _tr)
    _tr := array.from(-0.3074620811, -0.003482298349, 0.09333685745, -0.1487904956, 0.1701494168, 0.4517118931, 0.1155531751, -0.07302016501, -0.2269476947, -0.2326813349, -0.4440889077, -0.01424689108, 0.1764762183, -0.1390433479, 0.115063608, -0.137305451, -0.1494398777, 0.04601762217, 0.01471010359, -0.6805200576, -0.01985354825, 0.3298501623, -0.008314700378, 0.2401121678, -0.08366779725, 0.3991531106, 0.01297326504, -0.06297921291, 0.0623302478, 0.09600253171, -0.06303570907, 0.1057040854, -0.02572970538, -0.1715045903, 0.03320315621, -0.1990617291, 0.2404544094, 0.2430620157, -0.02401953102, -0.02030282536, 0.4528919585, 0.1155344853, 0.29577062, -0.1668417854, -0.005599342838, -0.3004249091, 0.1409598612, 0.05509300466, -0.4212824625, 0.0147588235, -0.111500117, -0.07359826768, 0.03555518965, 0.1606300345, -0.04901912341)
    array.concat(_tw, _tr)
    _tr := array.from(-0.2265385149, -0.1901236158, -0.1978626495, 0.1449747368, -0.3210903699, -0.1867207912, -0.02587529562, 0.05740020311, -0.4106205902, 0.2789821041, 0.3090227923, 0.1442368706, 0.167058902, -0.05202483261, 0.2337112457, 0.3172062533, -0.4033401707, 0.1273948721, -0.2332957069, 0.05734801887, 0.3440057835, 0.1765096368, 0.033558443, -0.5852202389, 0.181188866, 0.2177673288, 0.1441852958, -0.5120712166, -0.2357586022, 0.09234673118, 0.1072115013, 0.4317124168, 0.1154779627, 0.1245796933, 0.1450346597, 0.09206157953, 0.0623009626, 0.1943757463, 0.04376695388, -0.09789940656, 0.08798341836, 0.1295236573, 0.3625756814, 0.2740946463, 0.2788943893, 0.2435043217, 0.2771609081, 0.2094347242, -0.1092656775, -0.2784559916, -0.194593804, -0.2842300208, -0.4161920099, -0.146051506, -0.09340003725)
    array.concat(_tw, _tr)
    _tr := array.from(-0.168607685, -0.2836530886, -0.3912921061, -0.03978752215, 0.5606959855, -0.178294219, -0.05207609293, -0.0862340585, -0.06507860519, -0.05982634275, -0.08528710406, -0.101715063, -0.1922547823, 0.1381672292, -0.2122452912, 0.05176076625, -0.09925274607, -0.1454812424, 0.3543845187, 0.5896825973, -0.2692728039, -0.007337078868, -0.2497982367, -0.05448461555, -0.102058999, 0.1747837396, -0.1115309627, 0.2449387407, -0.09607997099, -0.1394593912, 0.0463811043, -0.09113068966, -0.1762160727, 0.1069910003, 0.08407302426, -0.2987575447, 0.3222411178, -0.1870106767, 0.02365883339, 0.3543389596, 0.03143924271, -0.1274054002, -0.3890747739, -0.186642131, -0.3828881879, -0.1488688467, -0.003377634599, -0.09500386713, -0.2003716761, -0.4118254893, 0.3945211614, -0.4357928209, -0.1072348842, 0.1534575573, 0.2352415428)
    array.concat(_tw, _tr)
    _tr := array.from(-0.2008270822, 0.119829278, 0.2507335074, -0.1962252464, 0.05629592504, -0.203990338, 0.2365825885, -0.4279187914, 0.2188554128, -0.08918333368, 0.05872209596, -0.3710934569, -0.2032552427, 0.08619962603, 0.3134622747, -0.02279704663, -0.02694140486, -0.09480043019, 0.3200816456, -0.02669869543, -0.02671874143, -0.1963718985, 0.06009797467, 0.1227731585, 0.3773142332, -0.04965135084, -0.1665934833, 0.07396975206, 0.1016486952, -0.4686561689, -0.06953252795, -0.02672698109, 0.2139776714, 0.1109758827, 0.08570513103, -0.09691819007, 0.5027528645, 0.2682054781, 0.1510679187, -0.05830955158, 0.290266119, -0.003622739899, -0.1133044379, -0.1129506698, -0.3012233339, -0.7137978583, 0.4075937155, -0.2111889272, -0.2424455727, 0.1937756641, 0.1616928597, -0.07721486257, -0.238664677, 0.06851580502, 0.4352718454)
    array.concat(_tw, _tr)
    _tr := array.from(-0.06559018767, 0.1253559449, 0.1451392613, 0.1454651703, -0.01874316031, 0.1572181722, -0.4539587811, 0.1679372167, -0.1079834977, 0.1748757515, -0.08511948592, -0.5116601525, -0.3063405457, -0.1388497358, -0.05563589165, -0.01927195708, -0.5757766271, -0.2041204656, 0.2168459671, 0.1622401376, 0.2803300215, 0.004501053985, -0.08087381539, -0.01735016643, 0.0907165616, -0.5812555272, 0.2894778583, -0.04364317346, -0.2249492117, 0.2730331891, -0.05621150575, -0.07702685376, -0.4612515819, 0.001332938906, -0.1705505985, -0.00277280422, -0.1121825716, 0.1224950572, -0.2158445923, 0.1025291993, -0.1357225214, -0.370390042, -0.09674313098, 0.176536063, 0.3637777172, 0.1513138123, -0.02757970533, 0.09366383633, 0.1777884849, 0.1790392809, 0.003502640902, 0.4948605465, -0.3090684786, 0.3432085212, 0.01880613463)
    array.concat(_tw, _tr)
    _tw

_fw_COINBASE_BTCUSD_8H_b1() =>
    array.from(0.2797560829, 0.2793794544, -0.02024683686, -0.1790240799, -0.2147024528, 0.4258214351, -0.03699615533, 0.02063114315, 0.1273634823, -0.198662241, -0.2429692734, 0.032730811, -0.3487665325, 0.1455379289, -0.06884516944, 0.3871496126)

_fw_COINBASE_BTCUSD_8H_w2() =>
    float[] _tw = array.from(-0.3403647479, -0.05014207103, 0.5656310752, -0.1946719999, -0.4810671228, 0.5438433905, -0.03230783335, 0.2687519874, -0.1909346266, -0.5035515625, 0.15794582, -0.1342641721, -0.1884755832, 0.4346730094, -0.2381253884, 0.1792157952)
    float[] _tr = array.from(-0.01074756138, -0.2410816375, 0.05872243487, 0.2155052188, 0.01732291673, 0.4332573766, -0.4309140076, 0.4008924005, -0.2978917667, -0.4348916838, -0.4978348809, 0.1257814558, -0.148977963, -0.3739372091, -0.2401831071, -0.03373115268)
    array.concat(_tw, _tr)
    _tr := array.from(0.4951241671, -0.5067139524, -0.01821272438, -0.3418945183, -0.03739217136, 0.1134412632, 0.09500532265, -0.062199209, -0.3175084482, -0.7689851807, -0.2882637624, 0.3681208476, 0.02998616896, 0.1523099855, 0.0383388668, 0.09235613112)
    array.concat(_tw, _tr)
    _tr := array.from(-0.1137013212, 0.4732807055, -0.1973446303, -0.01550603961, 0.3988849562, 0.1250026857, 0.2969556547, 0.4109873772, 0.2585165123, 0.1258275398, 0.3190761491, 0.08174038121, -0.349572169, 0.01562072063, -0.6201166166, -0.04403637836)
    array.concat(_tw, _tr)
    _tr := array.from(-0.2113247656, 0.07269610331, -0.147874932, 0.5140660558, -0.3752686258, 0.1046927931, -0.01470461458, 0.1281248991, 0.09050857054, -0.3118228993, 0.1423698787, -0.1774112065, 0.05383669873, 0.112012412, -0.1166562995, 0.1123158422)
    array.concat(_tw, _tr)
    _tr := array.from(-0.03176207453, -0.803277234, -0.2510709514, 0.3228890412, 0.1796365661, -0.0803073782, -0.1848392554, -0.5243462098, 0.09096849766, 0.3460557845, 0.2773977876, 0.1038699008, 0.02132116771, -0.06618120152, -0.3856813743, -0.2588464537)
    array.concat(_tw, _tr)
    _tr := array.from(-0.03464144532, -0.24983385, 0.1803495888, -0.08408414247, 0.05084210727, -0.1364158085, 0.3100346984, 0.1878802737, -0.3470639665, -0.1603753495, -0.3434703617, -0.1217881439, 0.2191018535, 0.009452214931, 0.08891095617, -0.1181836483)
    array.concat(_tw, _tr)
    _tr := array.from(-0.5073821399, -0.06927745665, -0.163764542, -0.0984142231, 0.07968078321, -0.03282957872, 0.2185706511, 0.4116329187, -0.3396911284, -0.1660128256, 0.2070727763, -0.2338014599, -0.1123696175, 0.223840517, 0.09247776309, 0.2896757301)
    array.concat(_tw, _tr)
    _tw

_fw_COINBASE_BTCUSD_8H_b2() =>
    array.from(0.4752759529, -0.1354942472, 0.3752380976, 0.0146223275, -0.05955206016, 0.05705752503, -0.3226720594, 0.2139992971)

_fw_COINBASE_BTCUSD_8H_w3() =>
    array.from(-0.2202049263, -0.3508318841, -0.2295123908, 0.3118666306, -0.2491773678, 0.06172751554, -0.09414517468, 0.04334002718)

_fw_COINBASE_BTCUSD_8H_b3() =>
    array.from(-0.5429190158)

if barstate.isfirst and _preset == "COINBASE_BTCUSD 4H"
    _w1 := _fw_COINBASE_BTCUSD_4H_w1()
    _b1 := _fw_COINBASE_BTCUSD_4H_b1()
    _w2 := _fw_COINBASE_BTCUSD_4H_w2()
    _b2 := _fw_COINBASE_BTCUSD_4H_b2()
    _w3 := _fw_COINBASE_BTCUSD_4H_w3()
    _b3 := _fw_COINBASE_BTCUSD_4H_b3()

if barstate.isfirst and _preset == "COINBASE_BTCUSD 8H"
    _w1 := _fw_COINBASE_BTCUSD_8H_w1()
    _b1 := _fw_COINBASE_BTCUSD_8H_b1()
    _w2 := _fw_COINBASE_BTCUSD_8H_w2()
    _b2 := _fw_COINBASE_BTCUSD_8H_b2()
    _w3 := _fw_COINBASE_BTCUSD_8H_w3()
    _b3 := _fw_COINBASE_BTCUSD_8H_b3()

// ── END AUTO-GENERATED ─────────────────────────────────────────────────────────────────────


group_candlestick_patterns = "Candlestick Patterns"
// NOTE: these are NOT preset-switched (not in optimizer params); declared here as static inputs.
// Bullish Hammer
i_cs_hammer_min_lower_shadow    = input.float(0.60,  step=0.05, title="Hammer Min Lower Shadow Ratio",   group=group_candlestick_patterns, display=display.none)
i_cs_hammer_max_body_ratio      = input.float(0.35,  step=0.05, title="Hammer Max Body Ratio",           group=group_candlestick_patterns, display=display.none)
i_cs_hammer_max_upper_shadow    = input.float(0.15,  step=0.05, title="Hammer Max Upper Shadow Ratio",   group=group_candlestick_patterns, display=display.none)
// Bullish / Bearish Engulfing
i_cs_body_quality_ratio         = input.float(0.55, step=0.05, title="Engulfing Body Quality Ratio",    group=group_candlestick_patterns, display=display.none)
i_cs_confidence_scaling_factor  = input.float(12.0, step=0.1,  title="Bear Engulfing Confidence Scale", group=group_candlestick_patterns, display=display.none)
i_cs_bull_eng_scaling_factor    = input.float(12.0, step=0.1,  title="Bull Engulfing Confidence Scale", group=group_candlestick_patterns, display=display.none)
// Shooting Star
i_cs_star_min_upper_shadow      = input.float(0.60,  step=0.05, title="Shooting Star Min Upper Shadow",  group=group_candlestick_patterns, display=display.none)
i_cs_star_max_body_ratio        = input.float(0.35,  step=0.05, title="Shooting Star Max Body Ratio",    group=group_candlestick_patterns, display=display.none)
i_cs_star_max_lower_shadow      = input.float(0.15,  step=0.05, title="Shooting Star Max Lower Shadow",  group=group_candlestick_patterns, display=display.none)

group_gc = "Gaussian Channel Settings"
i_gc_poles = input.int(4,     minval=1, maxval=9, title="Poles",        group=group_gc, display=display.none)
i_gc_per   = input.int(144,   minval=2,           title="Sampling Period", group=group_gc, display=display.none)
i_gc_mult  = input.float(1.414, step=0.1,         title="TR Multiplier",   group=group_gc, display=display.none)

// ── MVRV Macro Regime Classification ────────────────────────────────────────
group_mvrv_regime = "MVRV Macro Regime"
i_mvrv_regime_show        = input.bool(true,  title="Show Regime Background",            group=group_mvrv_regime)
i_mvrv_bear_threshold     = input.float(21.0, step=1.0, title="Bear Threshold (zscore < X)",   group=group_mvrv_regime,
    tooltip="Bars below this percentile are classified as Bear.")
i_mvrv_bull_threshold     = input.float(30.0, step=1.0, title="Bull Threshold (zscore ≥ X)",   group=group_mvrv_regime,
    tooltip="Bars at or above this percentile are classified as Bull.")

groupM3          = "M3 Settings"
m3_growth_rate_period_1D        = input.int(92, "Growth Rate Period (1D)", group=groupM3,display=display.none)
m3_growth_rate_period_12H       = input.int(92, "Growth Rate Period (12H)", group=groupM3,display=display.none)

m3_globalSmoothingMethod          = input.string(title="Money Supply Smoothing Method", options=["None", "Simple Moving Average", "Exponential Moving Average", "Hull Moving Average"],  defval="None", group=groupM3, display=display.none)
m3_globalSmoothingPeriod_1D       = input.int(14, title="Global Smoothing Period (1D)", minval=1, group=groupM3, display=display.none)
m3_globalSmoothingPeriod_12H      = input.int(14, title="Global Smoothing Period (12H)", minval=1, group=groupM3, display=display.none)

smoothM3SmoothingMethod           = input.string(title="Smooth M3 Moving Average", options=["None", "Simple Moving Average", "Exponential Moving Average", "Hull Moving Average"], defval="Exponential Moving Average", group=groupM3, display=display.none)
smoothM3SmoothingPeriod_1D        = input.int(5, title="Smooth M3 Smoothing Period (1D)", minval=1, group=groupM3, display=display.none)
smoothM3SmoothingPeriod_12H       = input.int(5, title="Smooth M3 Smoothing Period (12H)", minval=1, group=groupM3, display=display.none)

timeframe_divisor = utils.f_resInDays()
var int m3_growth_rate_period_tf      = na
var int m3_globalSmoothingPeriod_tf   = na
var int smoothM3SmoothingPeriod_tf    = na
m3_growth_rate_period_tf    := utils.f_getParamForTimeframe_int(m3_growth_rate_period_1D, m3_growth_rate_period_12H, m3_growth_rate_period_1D)
m3_globalSmoothingPeriod_tf := utils.f_getParamForTimeframe_int(m3_globalSmoothingPeriod_1D, m3_globalSmoothingPeriod_12H, m3_globalSmoothingPeriod_1D)
smoothM3SmoothingPeriod_tf  := utils.f_getParamForTimeframe_int(smoothM3SmoothingPeriod_1D, smoothM3SmoothingPeriod_12H, smoothM3SmoothingPeriod_1D)

moneySupplyInputs = libMoneySupply.MoneySupplySettings.new()
moneySupplyInputs.m3_growth_rate_period := m3_growth_rate_period_tf
moneySupplyInputs.m3_globalSmoothingMethod := m3_globalSmoothingMethod
moneySupplyInputs.m3_globalSmoothingPeriod := m3_globalSmoothingPeriod_tf
moneySupplyInputs.smoothM3SmoothingMethod := smoothM3SmoothingMethod
moneySupplyInputs.smoothM3SmoothingPeriod := smoothM3SmoothingPeriod_tf

moneySupplyData = libMoneySupply.calculate_money_supply(moneySupplyInputs)
m2_US_EU_CN = moneySupplyData.m2_US_EU_CN
m3_global_smoothed = moneySupplyData.m3_global_smoothed

m3_div_osc = libM3Div.f_calc_oscillator(m3_global_smoothed, close)

//{ MACD Setup }
macd_settings = macdLib.MACDSettings.new()
fast_length_1D                      = input.int(12,"Fast Length (1D)", group="MACD", display=display.none)
fast_length_12H                     = input.int(15,"Fast Length (12H)", group="MACD", display=display.none)
macd_settings.fast_length           := utils.f_getParamForTimeframe_int(fast_length_1D, fast_length_12H, fast_length_1D)
slow_length_1D                      = input.int(26,"Slow Length (1D)", group="MACD", display=display.none)
slow_length_12H                     = input.int(35,"Slow Length (12H)", group="MACD", display=display.none)
macd_settings.slow_length           := utils.f_getParamForTimeframe_int(slow_length_1D, slow_length_12H, slow_length_1D)
signal_length_1D                    = input.int(9,"Signal Smoothing (1D)",minval=1,maxval=50,group="MACD", display=display.none)
signal_length_12H                   = input.int(9,"Signal Smoothing (12H)",minval=1,maxval=50,group="MACD", display=display.none)
macd_settings.signal_length         := utils.f_getParamForTimeframe_int(signal_length_1D, signal_length_12H, signal_length_1D)
macd_settings.sma_source            := input.string("EMA","Oscillator MA Type",options=["SMA","EMA"],group="MACD", display=display.none)
macd_settings.sma_signal            := input.string("EMA","Signal Line MA Type",options=["SMA","EMA"],group="MACD", display=display.none)
macd_settings.i_macd_slope_threshold_percent := input(-9.0, "MACD Slope Threshold (%)", group="MACD", display=display.none)

bullishFlipSignalBars_1D            = input.int(1, "Bullish Flip Stability (1D)",group="MACD", display=display.none)
bullishFlipSignalBars_12H           = input.int(1, "Bullish Flip Stability (12H)",group="MACD", display=display.none)
bearishFlipSignalBars_1D            = input.int(2, "Bearish Flip Stability (1D)",group="MACD", display=display.none)
bearishFlipSignalBars_12H           = input.int(2, "Bearish Flip Stability (12H)",group="MACD", display=display.none)
nBarsOut_1D                         = input.int(5,"N Bars Out for Prediction (1D)",group="MACD", display=display.none)
nBarsOut_12H                        = input.int(10,"N Bars Out for Prediction (12H)",group="MACD", display=display.none)
macd_settings.bullishFlipSignalBars := utils.f_getParamForTimeframe_int(bullishFlipSignalBars_1D, bullishFlipSignalBars_12H, bullishFlipSignalBars_1D)
macd_settings.bearishFlipSignalBars := utils.f_getParamForTimeframe_int(bearishFlipSignalBars_1D, bearishFlipSignalBars_12H, bearishFlipSignalBars_1D)
macd_settings.nBarsOut              := utils.f_getParamForTimeframe_int(nBarsOut_1D, nBarsOut_12H, nBarsOut_1D)

macd_source  = input(title="Source",defval=close, group="MACD", display=display.none)
macd_results = macdLib.calculate_macd(macd_source, macd_settings)

macd = macd_results.macd
signal = macd_results.signal
hist = macd_results.hist
isMacdHistRising = macd_results.isMacdHistRising
isMacdHistFalling = macd_results.isMacdHistFalling
macd_slope_above_threshold = macd_results.macd_slope_above_threshold
macd_is_increasing = macd_results.macd_is_increasing
macd_is_decreasing = macd_results.macd_is_decreasing
macd_prediction = macd_results.macd_prediction
macd_flipped_bullish = macd_results.macd_flipped_bullish
macd_flipped_bearish = macd_results.macd_flipped_bearish
macdLongEntryCondition = macd_results.macdLongEntryCondition
macdLongExitCondition = macd_results.macdLongExitCondition
macd_slope_current = macd_results.macd_slope_current
isMacdMinusMacdOneRising = macd_results.isMacdMinusMacdOneRising
macd_signal_difference_percentage = macd_results.macd_signal_difference_percentage
isMacdRising_len2 = macd_results.isMacdRising_len2
//} ========================

//{ Stochastic RSI Calculation }
groupStochRSI       = "Stochastic RSI Settings"
stochMasterSwitch   = input.string("Enabled", title="Stochastic RSI Master Switch", options=["Enabled","Disabled"], group= groupStochRSI, display=display.none)
smoothK_1D          = input.int(4,  "K (1D)", minval=1, group= groupStochRSI, display=display.none)
smoothK_12H         = input.int(2,  "K (12H)", minval=1, group= groupStochRSI, display=display.none)
smoothK             = utils.f_getParamForTimeframe_int(smoothK_1D, smoothK_12H, smoothK_1D)
smoothD             = input.int(3,  "D", minval=1, group= groupStochRSI, display=display.none)
lengthRSI           = input.int(10, "RSI Length", minval=1, group= groupStochRSI, display=display.none)
lengthStoch_1D      = input.int(17, "Stochastic Length (1D)", minval=1, group= groupStochRSI, display=display.none)
lengthStoch_12H     = input.int(32, "Stochastic Length (12H)", minval=1, group= groupStochRSI, display=display.none)
src_stoch           = input(close,  title="RSI Source", group= groupStochRSI, display=display.none)
stoch_tf            = input.timeframe("", "Stoch RSI Timeframe", group= groupStochRSI, display=display.none)
stoch_high_limit    = input.int(87, title="Stochastic High Limit", group= groupStochRSI, display=display.none)
stoch_low_limit     = input.int(20, title="Stochastic Low Limit", group= groupStochRSI, display=display.none)

calcStoch() =>
    rsi_val = ta.rsi(src_stoch, lengthRSI)
    stoch_1D = ta.stoch(rsi_val, rsi_val, rsi_val, lengthStoch_1D)
    stoch_12H = utils.f_dynamic_stoch(rsi_val, rsi_val, rsi_val, utils.f_getParamForTimeframe_int(lengthStoch_1D, lengthStoch_12H, lengthStoch_1D))
    stoch_val = timeframe.period == "D" ? stoch_1D : stoch_12H
    ta.sma(stoch_val, smoothK)

stoch_value         = stoch_tf == "" ? calcStoch() : request.security(syminfo.tickerid, stoch_tf, calcStoch(), gaps=barmerge.gaps_off, lookahead=barmerge.lookahead_off)
bool stochCondition = stochMasterSwitch == "Enabled" ? (stoch_value > stoch_high_limit or stoch_value < stoch_low_limit) : true
osc_high_limit      = input.int(67, title="Maximum RSI allowed on regular long entry condition(67)", group= groupStochRSI, display=display.none)
osc_src             = input(low, "OSC source(low)", group= groupStochRSI, display=display.none)

//{ Stochastic Divergence }
groupStochDiv = "Stochastic Divergence"
stochDiv_stochLength_1D      = input.int(14, title="Stochastic Length (1D)", minval=1, group=groupStochDiv, display=display.none)
stochDiv_stochLength_12H     = input.int(14, title="Stochastic Length (12H)", minval=1, group=groupStochDiv, display=display.none)
stochDiv_pivotLookback_1D    = input.int(5, title="Pivot Lookback Bars (1D)", minval=1, group=groupStochDiv, display=display.none)
stochDiv_pivotLookback_12H   = input.int(20, title="Pivot Lookback Bars (12H)", minval=1, group=groupStochDiv, display=display.none)

stochDivSettings = libStochDiv.StochasticDivergenceSettings.new()
stochDivSettings.smoothK := input.int(3, title="K Smoothing", minval=1, group=groupStochDiv, display=display.none)
stochDivSettings.smoothD := input.int(3, title="D Smoothing", minval=1, group=groupStochDiv, display=display.none)
stochDivSettings.maTypeK := input.string("Simple Moving Average", "MA Type K", options=["Simple Moving Average", "Exponential Moving Average", "Weighted Moving Average", "Hull Moving Average", "Volume Weighted Moving Average", "Volume Weighted Average Price", "None"], group=groupStochDiv, display=display.none)
stochDivSettings.maTypeD := input.string("Exponential Moving Average", "MA Type D", options=["Simple Moving Average", "Exponential Moving Average", "Weighted Moving Average", "Hull Moving Average", "Volume Weighted Moving Average", "Volume Weighted Average Price", "None"], group=groupStochDiv, display=display.none)
stochDivSettings.divergenceStrength := input.int(2, title="Divergence Strength (bars away)", minval=1, group=groupStochDiv, display=display.none)
stochDivSettings.stochLength   := utils.f_getParamForTimeframe_int(stochDiv_stochLength_1D, stochDiv_stochLength_12H, stochDiv_stochLength_1D)
stochDivSettings.pivotLookback := utils.f_getParamForTimeframe_int(stochDiv_pivotLookback_1D, stochDiv_pivotLookback_12H, stochDiv_pivotLookback_1D)

var float stoch_div_k_val = na
var bool stoch_bullishDivergence = false, stoch_bearishDivergence = false
var bool stoch_is_peaking = false, stoch_is_bottoming = false
[temp_bull, temp_bear, temp_k, temp_peaking, temp_bottoming] = libStochDiv.f_calc(stoch_value, stochDivSettings)
stoch_bullishDivergence := temp_bull
stoch_bearishDivergence := temp_bear
stoch_div_k_val := temp_k
stoch_is_peaking := temp_peaking
stoch_is_bottoming := temp_bottoming

stoch_roc = ta.roc(stoch_div_k_val, 1)
price_roc = ta.roc(close, 1)
stoch_div_osc = price_roc - stoch_roc
stoch_div_osc_hist = stoch_div_osc - stoch_div_osc[1]
//} ========================

//{ VWAP Divergence }
groupVwapDiv = "VWAP Divergence"
vwapDiv_pivotLookbackLeft_1D  = input.int(1, title="Pivot Lookback Left (1D)", minval=1, group=groupVwapDiv, display=display.none)
vwapDiv_pivotLookbackLeft_12H = input.int(1, title="Pivot Lookback Left (12H)", minval=1, group=groupVwapDiv, display=display.none)
vwapDiv_pivotLookbackRight_1D = input.int(1, title="Pivot Lookback Right (1D)", minval=1, group=groupVwapDiv, display=display.none)
vwapDiv_pivotLookbackRight_12H= input.int(1, title="Pivot Lookback Right (12H)", minval=1, group=groupVwapDiv, display=display.none)

vwapDivSettings = libVwapDiv.VWAPDivergenceSettings.new()
vwapDivSettings.pivotLookbackLeft := utils.f_getParamForTimeframe_int(vwapDiv_pivotLookbackLeft_1D, vwapDiv_pivotLookbackLeft_12H, vwapDiv_pivotLookbackLeft_1D)
vwapDivSettings.pivotLookbackRight := utils.f_getParamForTimeframe_int(vwapDiv_pivotLookbackRight_1D, vwapDiv_pivotLookbackRight_12H, vwapDiv_pivotLookbackRight_1D)
vwapDivSettings.divergenceStrength := input.int(2, title="Divergence Strength (bars away)", minval=1, group=groupVwapDiv, display=display.none)

var float vwap_value = na
var bool vwap_bullishDivergence = false, vwap_bearishDivergence = false
[temp_vwap_bull, temp_vwap_bear, temp_vwap_val] = libVwapDiv.f_calc(vwapDivSettings)
vwap_bullishDivergence := temp_vwap_bull
vwap_bearishDivergence := temp_vwap_bear
vwap_value := temp_vwap_val
vwap_div_osc = price_roc - ta.roc(vwap_value, 1)

//{ Stoch and RSI range filter }
groupStochAndRSI               = "Stoch and RSI range filter Long Entry"
stochRSI_len_1D                = input.int(14, "Stoch and RSI length (1D)", minval=1, group=groupStochAndRSI, display=display.none)
stochRSI_len_12H               = input.int(14, "Stoch and RSI length (12H)", minval=1, group=groupStochAndRSI, display=display.none)
rsi_lowpass_filter             = input.int(30, "RSI Threshold for Low(30)", minval=1, group=groupStochAndRSI, display=display.none)
rsi_highpass_filter            = input.int(60, "RSI Threshold for High(60)", minval=1, group=groupStochAndRSI, display=display.none)
stochvalue_lowpass_filter      = input.int(37, "Stoch Value Threshold for Low(?)", minval=1, group=groupStochAndRSI, display=display.none)
stochvalue_highpass_filter     = input.int(70, "Stoch Value Threshold for High(?)", minval=1, group=groupStochAndRSI, display=display.none)

// Calculate OSC for all supported timeframes unconditionally.
osc_1D = ta.rsi(osc_src, stochRSI_len_1D)
osc_12H = utils.f_dynamic_rsi(osc_src, utils.f_getParamForTimeframe_int(stochRSI_len_1D, stochRSI_len_12H, stochRSI_len_1D))
osc = timeframe.period == "D" ? osc_1D : osc_12H

//{ RSI Divergence }
rsid_label = "RSI Divergence"
i_rsid_src            = input(close, title="RSID Source", group=rsid_label, display=display.none)
i_rsid_lookback_1D    = input.int(14, title="Look-back (1D)",  minval=1, step=1,group=rsid_label, display=display.none)
i_rsid_lookback_12H   = input.int(9, title="Look-back (12H)",  minval=1, step=1,group=rsid_label, display=display.none)
i_rsid_lookback       = utils.f_getParamForTimeframe_int(i_rsid_lookback_1D, i_rsid_lookback_12H, i_rsid_lookback_1D)
i_rsid_overbought_1D  = input.int(70, title="Overbought (1D)", minval=1, step=1, group=rsid_label, display=display.none)
i_rsid_overbought_12H = input.int(75, title="Overbought (12H)", minval=1, step=1, group=rsid_label, display=display.none)
i_rsid_overbought     = utils.f_getParamForTimeframe_int(i_rsid_overbought_1D, i_rsid_overbought_12H, i_rsid_overbought_1D)
i_rsid_oversold_1D    = input.int(30, title="Oversold (1D)", minval=1, step=1, group=rsid_label, display=display.none)
i_rsid_oversold_12H   = input.int(20, title="Oversold (12H)", minval=1, step=1, group=rsid_label, display=display.none)
i_rsid_oversold       = utils.f_getParamForTimeframe_int(i_rsid_oversold_1D, i_rsid_oversold_12H, i_rsid_oversold_1D)
i_rsid_len_1D         = input.int(14, minval=1, title="RSI Length (1D)", group=rsid_label, display=display.none)
i_rsid_len_12H        = input.int(22, minval=1, title="RSI Length (12H)", group=rsid_label, display=display.none)
i_rsid_res            = input.timeframe("", title="Oscillator resolution", group=rsid_label, display=display.none)

var int i_rsid_len = na
i_rsid_len                := utils.f_getParamForTimeframe_int(i_rsid_len_1D, i_rsid_len_12H, i_rsid_len_1D)

rsi_1D = ta.rsi(i_rsid_src, i_rsid_len_1D)
rsi_12H = utils.f_dynamic_rsi(i_rsid_src, i_rsid_len)
rsi = timeframe.period == "D" ? rsi_1D : rsi_12H

rsid_osc = rsi

rsid_div_leftbars   = input.int(5,    "Div Pivot Left Bars",           minval=1,   group=rsid_label, display=display.none)
rsid_div_rightbars  = input.int(5,    "Div Pivot Right Bars",          minval=1,   group=rsid_label, display=display.none)
rsid_div_range_lo   = input.int(5,    "Div Range Lower (bars)",        minval=1,   group=rsid_label, display=display.none)
rsid_div_range_hi   = input.int(60,   "Div Range Upper (bars)",        minval=1,   group=rsid_label, display=display.none)
rsid_bb_len         = input.int(20,   "Div BB Length",                 minval=2,   group=rsid_label, display=display.none)
rsid_bb_mult        = input.float(2.0,"Div BB Multiplier",             step=0.1,   group=rsid_label, display=display.none)
rsid_rt_lookback    = input.int(100,  "RT Div Lookback",               minval=1,   group=rsid_label, display=display.none)
rsid_delayed_buf    = input.int(0,    "Delayed Peak/Dip Buffer Bars",  minval=0,   group=rsid_label, display=display.none)

rsid_pl = rsiDiv.plFound(rsi, rsid_div_leftbars, rsid_div_rightbars)
rsid_ph = rsiDiv.phFound(rsi, rsid_div_leftbars, rsid_div_rightbars)

rsid_reg_bull  = rsiDiv.regularBullish( rsi, close, rsid_div_rightbars, rsid_div_range_lo, rsid_div_range_hi, rsid_pl)
rsid_reg_bear  = rsiDiv.regularBearish( rsi, close, rsid_div_rightbars, rsid_div_range_lo, rsid_div_range_hi, rsid_ph)
rsid_hid_bull  = rsiDiv.hiddenBullish(  rsi, close, rsid_div_rightbars, rsid_div_range_lo, rsid_div_range_hi, rsid_pl)
rsid_hid_bear  = rsiDiv.hiddenBearish(  rsi, close, rsid_div_rightbars, rsid_div_range_lo, rsid_div_range_hi, rsid_ph)
rsid_rt_bull   = rsiDiv.realTimeBullishDiv(rsi, close, rsid_rt_lookback, i_rsid_oversold,  rsid_bb_len, rsid_bb_mult)
rsid_rt_bear   = rsiDiv.realTimeBearishDiv(rsi, close, rsid_rt_lookback, i_rsid_overbought)
rsid_slow_bull = rsiDiv.slowingBullish(rsi, i_rsid_oversold)
rsid_slow_bear = rsiDiv.slowingBearish(rsi, i_rsid_overbought)
rsid_delayed_peak = rsiDiv.delayedPeakRSI(rsi, i_rsid_overbought, rsid_delayed_buf)
rsid_delayed_dip  = rsiDiv.delayedDipRSI( rsi, i_rsid_oversold,   rsid_delayed_buf)
//} ========================

group_m2LeadingIndicator_calculations  = "M2 Leading Indicator Calculations"
m2LeadingIndicator_scalingLookback     = input.int(150, title="Scaling Lookback Period(150)", minval=2, group=group_m2LeadingIndicator_calculations, display=display.none)
i_m2LeadingIndicator_smoothingMethod   = input.string("Hull Moving Average", title="M2 Smoothing Method", options=["None", "Simple Moving Average", "Exponential Moving Average", "Hull Moving Average"], group="M2LI", display=display.none)
i_m2LeadingIndicator_barsToRightOfShortLength = input.int(10,"Bars from short length for diff/slope calculations(10)", group="M2LI", display=display.none)
i_m2LeadingIndicator_tinyOffset        = input.int(48, "Tiny offset, orange line(48)", group=group_m2LeadingIndicator_calculations, display=display.none)
i_m2LeadingIndicator_tinyOffset_smoothingLength = input.int(13, "Tiny Offset Smoothing Length(13)", group=group_m2LeadingIndicator_calculations, display=display.none)
i_m2LeadingIndicator_shortOffset       = input.int(64, "Short offset, orange line(64)", group=group_m2LeadingIndicator_calculations, display=display.none)
i_m2LeadingIndicator_shortOffset_smoothingLength = input.int(13, "Short Offset Smoothing Length(13)", group=group_m2LeadingIndicator_calculations, display=display.none)
i_m2LeadingIndicator_mediumOffset      = input.int(78, "Medium offset, red line", group=group_m2LeadingIndicator_calculations, display=display.none)
i_m2LeadingIndicator_mediumOffset_smoothingLength = input.int(16, "Medium Offset Smoothing Length", group=group_m2LeadingIndicator_calculations, display=display.none)
i_m2LeadingIndicator_longOffset        = input.int(92, "Long offset, yellow line(92)", group=group_m2LeadingIndicator_calculations, display=display.none)
i_m2LeadingIndicator_longOffset_smoothingLength = input.int(20, "Long Offset Smoothing Length", group=group_m2LeadingIndicator_calculations, display=display.none)
i_m2LeadingIndicator_riseFallLength    = input.int(3, "Length to use for calculating Rise/Fall", group=group_m2LeadingIndicator_calculations, display=display.none)
i_m2LeadingIndicator_oneDayOffset      = input.int(1, "Adjustment factor for one day, unclear if scaling it is needed", group=group_m2LeadingIndicator_calculations, display=display.none)
i_enable_timeframe_adjustment           = input.bool(true, title="Enable Time Frame Adjustment", group="General Setings",display=display.none)

if i_enable_timeframe_adjustment
    m2LeadingIndicator_scalingLookback                := int(m2LeadingIndicator_scalingLookback / timeframe_divisor) > 5000 ? 5000 : int(m2LeadingIndicator_scalingLookback/ timeframe_divisor)
    i_m2LeadingIndicator_barsToRightOfShortLength     := int(i_m2LeadingIndicator_barsToRightOfShortLength / timeframe_divisor) > 5000 ? 5000 : int(i_m2LeadingIndicator_barsToRightOfShortLength/ timeframe_divisor)
    i_m2LeadingIndicator_tinyOffset                   := int(i_m2LeadingIndicator_tinyOffset / timeframe_divisor) > 5000 ? 5000 : int(i_m2LeadingIndicator_tinyOffset/ timeframe_divisor)
    i_m2LeadingIndicator_shortOffset                  := int(i_m2LeadingIndicator_shortOffset / timeframe_divisor) > 5000 ? 5000 : int(i_m2LeadingIndicator_shortOffset / timeframe_divisor)
    i_m2LeadingIndicator_shortOffset_smoothingLength  := int(i_m2LeadingIndicator_shortOffset_smoothingLength / timeframe_divisor) > 5000 ? 5000 : int(i_m2LeadingIndicator_shortOffset_smoothingLength/ timeframe_divisor)
    i_m2LeadingIndicator_mediumOffset                 := int(i_m2LeadingIndicator_mediumOffset / timeframe_divisor) > 5000 ? 5000 : int(i_m2LeadingIndicator_mediumOffset / timeframe_divisor)
    i_m2LeadingIndicator_mediumOffset_smoothingLength := int(i_m2LeadingIndicator_mediumOffset_smoothingLength / timeframe_divisor) > 5000 ? 5000 : int(i_m2LeadingIndicator_mediumOffset_smoothingLength/ timeframe_divisor)
    i_m2LeadingIndicator_longOffset                   := int(i_m2LeadingIndicator_longOffset / timeframe_divisor) > 5000 ? 5000 : int(i_m2LeadingIndicator_longOffset / timeframe_divisor)
    i_m2LeadingIndicator_longOffset_smoothingLength   := int(i_m2LeadingIndicator_longOffset_smoothingLength / timeframe_divisor) > 5000 ? 5000 : int(i_m2LeadingIndicator_longOffset_smoothingLength/ timeframe_divisor)
    i_m2LeadingIndicator_riseFallLength               := int(i_m2LeadingIndicator_riseFallLength  / timeframe_divisor) > 5000 ? 5000 : int(i_m2LeadingIndicator_riseFallLength / timeframe_divisor)
    i_m2LeadingIndicator_oneDayOffset                 := int(i_m2LeadingIndicator_oneDayOffset  / timeframe_divisor) > 5000 ? 5000 : int(i_m2LeadingIndicator_oneDayOffset / timeframe_divisor)

m2_smoothed_tinyOffset = utils.f_ma(m2_US_EU_CN, i_m2LeadingIndicator_smoothingMethod, i_m2LeadingIndicator_tinyOffset_smoothingLength)
m2_smoothed_shortOffset     = utils.f_ma(m2_US_EU_CN, i_m2LeadingIndicator_smoothingMethod, i_m2LeadingIndicator_shortOffset_smoothingLength)

valid_scaling_lookback = m2LeadingIndicator_scalingLookback < 2 ? 2 : m2LeadingIndicator_scalingLookback
m2_smoothed_tinyOffset_scaled   = utils.f_scale_ToRange(m2_smoothed_tinyOffset,  m2LeadingIndicator_scalingLookback, m2LeadingIndicator_scalingLookback)
m2_smoothed_shortOffset_scaled  = utils.f_scale_ToRange(m2_smoothed_shortOffset,  m2LeadingIndicator_scalingLookback, m2LeadingIndicator_scalingLookback)

m2_div_osc_tiny = libM3Div.f_calc_oscillator(m2_smoothed_tinyOffset_scaled[i_m2LeadingIndicator_tinyOffset], close)

m2_smoothed_noOffset = utils.f_ma(m2_US_EU_CN, i_m2LeadingIndicator_smoothingMethod, i_m2LeadingIndicator_shortOffset_smoothingLength)
m2_smoothed_noOffset_scaled = utils.f_scale_ToRange(m2_smoothed_noOffset, m2LeadingIndicator_scalingLookback, m2LeadingIndicator_scalingLookback)
m2_div_osc_noOffset = libM3Div.f_calc_oscillator(m2_smoothed_noOffset_scaled, close)

m2_smoothedTiny_N_bars_out = m2_smoothed_tinyOffset_scaled[i_m2LeadingIndicator_tinyOffset - i_m2LeadingIndicator_barsToRightOfShortLength]
m2_diff_abs_tinyOffset_to_future = m2_smoothedTiny_N_bars_out - m2_smoothed_tinyOffset_scaled[i_m2LeadingIndicator_tinyOffset]

// ─────────────────────────────────────────────────────────────────────────────
// Macro / Cross-Asset Signal Calculations
// ─────────────────────────────────────────────────────────────────────────────

f_pctrank(src, len) => ta.percentrank(src, len) / 100.0

spx_close   = request.security("SP:SPX",          "D", close, gaps=barmerge.gaps_off, lookahead=barmerge.lookahead_off)
dxy_close   = request.security("TVC:DXY",         "D", close, gaps=barmerge.gaps_off, lookahead=barmerge.lookahead_off)
vix_close   = request.security("CBOE:VIX",        "D", close, gaps=barmerge.gaps_off, lookahead=barmerge.lookahead_off)
btcd_close  = request.security("CRYPTOCAP:BTC.D", "D", close, gaps=barmerge.gaps_off, lookahead=barmerge.lookahead_off)
us10y_close = request.security("TVC:US10Y",       "D", close, gaps=barmerge.gaps_off, lookahead=barmerge.lookahead_off)
us2y_close  = request.security("TVC:US02Y",       "D", close, gaps=barmerge.gaps_off, lookahead=barmerge.lookahead_off)
spy_close   = request.security("AMEX:SPY",        "D", close, gaps=barmerge.gaps_off, lookahead=barmerge.lookahead_off)
gold_close  = request.security("TVC:GOLD",        "D", close, gaps=barmerge.gaps_off, lookahead=barmerge.lookahead_off)

btc_spx_corr_30 = ta.correlation(ta.roc(close, 1), ta.roc(nz(spx_close, spx_close[1]), 1), 30)

dxy_roc       = ta.roc(nz(dxy_close, dxy_close[1]), 14)
dxy_roc_norm  = dxy_roc > 0 ? -1.0 : dxy_roc < 0 ? 1.0 : 0.0

vix_pctrank_inv = 1.0 - f_pctrank(nz(vix_close, vix_close[1]), 252)

btc_dom_roc      = ta.roc(nz(btcd_close, btcd_close[1]), 7)
btc_dom_roc_sign = btc_dom_roc > 0 ? 1.0 : btc_dom_roc < 0 ? -1.0 : 0.0

us10y_roc        = ta.roc(nz(us10y_close, us10y_close[1]), 14)
us10y_roc_inv_sign = us10y_roc > 0 ? -1.0 : us10y_roc < 0 ? 1.0 : 0.0

us2y_roc          = ta.roc(nz(us2y_close, us2y_close[1]), 14)
us2y_roc_inv_sign = us2y_roc > 0 ? -1.0 : us2y_roc < 0 ? 1.0 : 0.0

yield_curve_spread = nz(us10y_close, us10y_close[1]) - nz(us2y_close, us2y_close[1])
yield_curve_sign   = yield_curve_spread > 0 ? 1.0 : yield_curve_spread < 0 ? -1.0 : 0.0

// SOPR (col 32) — Spent Output Profit Ratio: on-chain spending profit/loss state
_sopr_raw  = request.security("GLASSNODE:XTVCBTC_SOPR", "D", close, gaps=barmerge.gaps_off, lookahead=barmerge.lookahead_off)
sopr_norm  = (ta.percentrank(nz(_sopr_raw, 1.0), 365) - 50.0) / 50.0

spy_f = nz(spy_close, spy_close[1])
spy_above_200ema = spy_f > ta.ema(spy_f, 200) ? 1.0 : -1.0

gold_roc_pctrank = f_pctrank(ta.roc(nz(gold_close, gold_close[1]), 21), 252)

// ── Derivatives: Perp OI, USDT Dominance, Spot-Perp Basis ───────────────────
[_perp_close, _perp_vol] = request.security("BINANCE:BTCUSDTPERP", timeframe.period, [close, volume], gaps=barmerge.gaps_off, lookahead=barmerge.lookahead_off)
_usdt_d_raw = request.security("CRYPTOCAP:USDT.D",    timeframe.period, close,  gaps=barmerge.gaps_off, lookahead=barmerge.lookahead_off)

_oi_roc  = ta.roc(nz(_perp_vol, _perp_vol[1]), 3)
oi_roc_norm = (ta.percentrank(_oi_roc, 252) - 50.0) / 50.0

_usdt_roc   = ta.roc(nz(_usdt_d_raw, _usdt_d_raw[1]), 3)
usdt_d_norm = -((ta.percentrank(_usdt_roc, 252) - 50.0) / 50.0)

_basis_pct = (nz(_perp_close, _perp_close[1]) - close) / close * 100.0
basis_norm = math.max(-1.0, math.min(1.0, nz(_basis_pct, 0.0) / 0.5))

// ── Sentiment / Sub-TF Confirmation Signals ──────────────────────────────────
// CVD (col 46) — OBV ROC percentrank: buy/sell pressure imbalance
_cvd_roc   = ta.roc(ta.obv, 20)
cvd_norm   = (ta.percentrank(_cvd_roc, 252) - 50.0) / 50.0

_btc_gold_raw = gold_close > 0.0 ? close / gold_close : na
btc_gold_norm = -((ta.percentrank(nz(_btc_gold_raw, _btc_gold_raw[1]), 252) - 50.0) / 50.0)

_sub_tf_str = str.tostring(math.round(_tf_secs / 120))
_rsi_subtf_raw = request.security(syminfo.tickerid, _sub_tf_str, ta.rsi(close, 14), gaps=barmerge.gaps_off, lookahead=barmerge.lookahead_off)
rsi_subtf_norm = (nz(_rsi_subtf_raw, 50.0) - 50.0) / 50.0

// Bollinger Band %B — mean reversion signal (col 49)
// -1 = price at/below lower band (oversold), +1 = at/above upper band (overbought)
_bb_basis     = ta.sma(close, 20)
_bb_dev       = 2.0 * ta.stdev(close, 20)
bb_pct_b_norm = math.min(1.0, math.max(-1.0, 2.0 * (close - (_bb_basis - _bb_dev)) / math.max(_bb_dev * 2.0, 1e-9) - 1.0))

// ─────────────────────────────────────────────────────────────────────────────
// On-Chain Regime Signals
// ─────────────────────────────────────────────────────────────────────────────

mvrv_mc  = request.security("GLASSNODE:BTC_MARKETCAP",       "D", close, gaps=barmerge.gaps_off, lookahead=barmerge.lookahead_off)
mvrv_mcr = request.security("COINMETRICS:BTC_MARKETCAPREAL", "D", close, gaps=barmerge.gaps_off, lookahead=barmerge.lookahead_off)
mvrv_stdev = ta.stdev(nz(mvrv_mc, mvrv_mc[1]), 730)
mvrv_zscore_raw = mvrv_stdev > 0.0 ? (nz(mvrv_mc, mvrv_mc[1]) - nz(mvrv_mcr, mvrv_mcr[1])) / mvrv_stdev : 0.0
mvrv_zscore  = (mvrv_zscore_raw - (-0.57)) / (9.40 - (-0.57)) * 100.0
mvrv_highest = ta.ema(ta.highest(mvrv_zscore, 1200), 900)
mvrv_lowest  = ta.ema(ta.lowest(mvrv_zscore,  1500), 900)
mvrv_mid     = math.avg(mvrv_highest - 20, mvrv_lowest + 5)
var float mvrv_zscore_value = 0.0
if ta.crossover(mvrv_zscore, mvrv_highest - 20)
    mvrv_zscore_value := -1.0
if ta.crossunder(mvrv_zscore, mvrv_highest - 20)
    mvrv_zscore_value := -0.5
if ta.crossunder(mvrv_zscore, mvrv_lowest + 5)
    mvrv_zscore_value := 1.0
if ta.crossover(mvrv_zscore, mvrv_lowest + 5)
    mvrv_zscore_value := 0.5
if ta.crossunder(mvrv_zscore, mvrv_mid)
    mvrv_zscore_value := -0.25
if ta.crossover(mvrv_zscore, mvrv_mid)
    mvrv_zscore_value := 0.25

nupl_length      = i_enable_timeframe_adjustment ? math.max(2, math.min(5000, int(365.0 / timeframe_divisor))) : 365
realized_price   = ta.vwma(close, nupl_length)
nupl_pct         = realized_price > 0.0 ? (close - realized_price) / close * 100.0 : 0.0
nupl_norm        = math.min(1.0, math.max(-1.0, nupl_pct / 50.0))

_walcl_raw = request.security("FRED:WALCL", "W", close, gaps=barmerge.gaps_off, lookahead=barmerge.lookahead_off)
_fed_roc = ta.roc(nz(_walcl_raw, _walcl_raw[1]), 4)
float fed_net_liq_sign = _fed_roc > 0 ? 1.0 : _fed_roc < 0 ? -1.0 : 0.0

// ─────────────────────────────────────────────────────────────────────────────
// Supplemental features (cols 50–54) — also exported via strategy_mlp_feature_export.pine
// ─────────────────────────────────────────────────────────────────────────────

// CVD NORM (col 50) — reuses cvd_norm defined above (col 46 block)

// RVOL NORM (col 51) — realized vol vs historical; volatility regime signal
float _log_ret  = math.log(close / nz(close[1], close))
float _rvol_30  = ta.stdev(_log_ret, 30)
float rvol_norm = (ta.percentrank(_rvol_30, 252) - 50.0) / 50.0

// ACTIVE1Y NORM (col 52) — % supply inactive 1+ yr; long-term holder concentration
float _a1y_raw      = request.security("GLASSNODE:XTVCBTC_ACTIVE1Y", "D", close, gaps=barmerge.gaps_off, lookahead=barmerge.lookahead_off)
float active1y_norm = (ta.percentrank(nz(_a1y_raw, _a1y_raw[1]), 365) - 50.0) / 50.0

// HR NORM (col 53) — hash rate ROC; miner commitment signal
float _hr_raw  = request.security("GLASSNODE:XTVCBTC_HASHRATE", "D", close, gaps=barmerge.gaps_off, lookahead=barmerge.lookahead_off)
float _hr_roc  = ta.roc(nz(_hr_raw, _hr_raw[1]), 30)
float hr_norm  = (ta.percentrank(_hr_roc, 365) - 50.0) / 50.0

// SOPR NORM (col 54) — reuses sopr_norm defined above (col 32 block)

gcSettings = gcl.GaussianSettings.new(
    poles        = i_gc_poles,
    per          = i_gc_per,
    mult         = i_gc_mult,
    modeLag      = false,
    modeFast     = false,
    useAma       = false,
    amaLength    = 20,
    amaFast      = 2,
    amaSlow      = 30,
    useSimpleCalc = true)
[gc_hband, gc_lband, gc_filt, gc_green] = gcl.calc(close, gcSettings)
gc_position = close > gc_hband ? 1.0 : close < gc_lband ? -1.0 : 0.0
plotchar(gc_hband,    title="gc_hband",    color=color.gray, display=display.data_window)
plotchar(gc_lband,    title="gc_lband",    color=color.gray, display=display.data_window)
plotchar(gc_position, title="gc_position", color=color.gray, display=display.data_window)

// Candlestick Pattern Score Calculation
engulfingSettings = libCandlePatterns.EngulfingSettings.new()
engulfingSettings.body_quality_ratio := i_cs_body_quality_ratio
engulfingSettings.confidence_scaling_factor := i_cs_confidence_scaling_factor
bearish_engulfing_score = libCandlePatterns.f_calculateBearishEngulfingScore(engulfingSettings)

bullEngulfingSettings = libCandlePatterns.EngulfingSettings.new()
bullEngulfingSettings.body_quality_ratio := i_cs_body_quality_ratio
bullEngulfingSettings.confidence_scaling_factor := i_cs_bull_eng_scaling_factor
bullish_engulfing_score = libCandlePatterns.f_calculateBullishEngulfingScore(bullEngulfingSettings)

hammerSettings = libCandlePatterns.HammerSettings.new()
hammerSettings.min_lower_shadow_ratio := i_cs_hammer_min_lower_shadow
hammerSettings.max_body_ratio := i_cs_hammer_max_body_ratio
hammerSettings.max_upper_shadow_ratio := i_cs_hammer_max_upper_shadow
bullish_hammer_score = libCandlePatterns.f_calculateBullishHammerScore(hammerSettings)

shootingStarSettings = libCandlePatterns.ShootingStarSettings.new()
shootingStarSettings.min_upper_shadow_ratio := i_cs_star_min_upper_shadow
shootingStarSettings.max_body_ratio := i_cs_star_max_body_ratio
shootingStarSettings.max_lower_shadow_ratio := i_cs_star_max_lower_shadow
shooting_star_score = libCandlePatterns.f_calculateShootingStarScore(shootingStarSettings)

// m3_momentum: period=1 locked in MLP pilot (single-bar lookback optimal)
m3_momentum = m3_global_smoothed - m3_global_smoothed[1]


// ─────────────────────────────────────────────────────────────────────────────
// MLP Forward Pass
// ─────────────────────────────────────────────────────────────────────────────

// tanh closed-form: formula-identical to Python strategy_mlp_scores._tanh and
// the Pine v6 tanh approximation (Pine has no math.tanh builtin).
f_tanh(x) =>
    x >= 20.0 ? 1.0 : x <= -20.0 ? -1.0 : (math.exp(2.0 * x) - 1.0) / (math.exp(2.0 * x) + 1.0)

// Feature vector _x[49] — matches Python FEATURE_COLS order exactly.
// NOTE: cols 3 (macd_bullish_norm), 6 (rsid_norm), 10 (stoch_bot_norm) were absent
// from perceptron Pine plotchar exports; existing training CSVs have 0 for those cols.
// MLP weights for those features will be near-zero after training on perceptron CSVs.
var float[] _x = array.new_float(55, 0.0)
array.set(_x,  0, (stoch_value - 50.0) / 50.0)                                                         // stoch_norm
array.set(_x,  1, macd_prediction > 0.0 ? 1.0 : -1.0)                                                  // macd_pred_norm
array.set(_x,  2, (osc_1D - 50.0) / 50.0)                                                              // osc_norm
array.set(_x,  3, macd_flipped_bullish ? 1.0 : 0.0)                                                    // macd_bullish_norm
array.set(_x,  4, m3_momentum > 0.0 ? 1.0 : -1.0)                                                     // m3_momentum_norm
array.set(_x,  5, m2_diff_abs_tinyOffset_to_future > 1e-9 ? 1.0 : m2_diff_abs_tinyOffset_to_future < -1e-9 ? -1.0 : 0.0)  // m2_tiny_norm
array.set(_x,  6, (rsi - 50.0) / 50.0)                                                                 // rsid_norm (normalised RSI)
array.set(_x,  7, stoch_div_osc > 0.0 ? 1.0 : stoch_div_osc < 0.0 ? -1.0 : 0.0)                     // stoch_div_norm
array.set(_x,  8, math.max(-1.0, math.min(1.0, vwap_div_osc)))                                        // vwap_div_norm
array.set(_x,  9, stoch_is_peaking ? -1.0 : 0.0)                                                      // stoch_peak_norm
array.set(_x, 10, stoch_is_bottoming ? 1.0 : 0.0)                                                     // stoch_bot_norm
array.set(_x, 11, m3_div_osc > 0.0 ? 1.0 : m3_div_osc < 0.0 ? -1.0 : 0.0)                          // m3_div_norm
array.set(_x, 12, bearish_engulfing_score)                                                              // bearish_engulfing_score
array.set(_x, 13, m2_div_osc_noOffset > 0.0 ? 1.0 : m2_div_osc_noOffset < 0.0 ? -1.0 : 0.0)        // m2_nooff_norm
array.set(_x, 14, m2_div_osc_tiny > 0.0 ? 1.0 : m2_div_osc_tiny < 0.0 ? -1.0 : 0.0)                // m2_div_norm
array.set(_x, 15, bullish_hammer_score)                                                                 // bullish_hammer_score
array.set(_x, 16, bullish_engulfing_score)                                                              // bullish_engulfing_score
array.set(_x, 17, shooting_star_score)                                                                  // shooting_star_score
array.set(_x, 18, btc_spx_corr_30)                                                                     // btc_spx_corr_30
array.set(_x, 19, dxy_roc_norm)                                                                         // dxy_roc_norm
array.set(_x, 20, vix_pctrank_inv)                                                                      // vix_pctrank_inv
array.set(_x, 21, btc_dom_roc_sign)                                                                     // btc_dom_roc_sign
array.set(_x, 22, us10y_roc_inv_sign)                                                                   // us10y_roc_inv_sign
array.set(_x, 23, spy_above_200ema)                                                                     // spy_above_200ema
array.set(_x, 24, gold_roc_pctrank)                                                                     // gold_roc_pctrank
array.set(_x, 25, mvrv_zscore_value)                                                                    // mvrv_zscore_value
array.set(_x, 26, math.min(1.0, math.max(-1.0, mvrv_zscore / 50.0 - 1.0)))                           // mvrv_zscore_cont
array.set(_x, 27, nupl_norm)                                                                            // nupl_norm
array.set(_x, 28, fed_net_liq_sign)                                                                    // fed_net_liq_sign
array.set(_x, 29, gc_position)                                                                          // gc_position
array.set(_x, 30, us2y_roc_inv_sign)                                                                   // us2y_roc_inv_sign
array.set(_x, 31, yield_curve_sign)                                                                     // yield_curve_sign
array.set(_x, 32, sopr_norm)                                                                            // sopr_norm
array.set(_x, 33, rsid_reg_bull ? 1.0 : 0.0)                                                          // rsid_reg_bull_norm (window=1)
array.set(_x, 34, rsid_reg_bear ? 1.0 : 0.0)                                                          // rsid_reg_bear_norm
array.set(_x, 35, rsid_hid_bull ? 1.0 : 0.0)                                                          // rsid_hid_bull_norm
array.set(_x, 36, rsid_hid_bear ? 1.0 : 0.0)                                                          // rsid_hid_bear_norm
array.set(_x, 37, rsid_rt_bull ? 1.0 : 0.0)                                                           // rsid_rt_bull_norm
array.set(_x, 38, rsid_rt_bear ? 1.0 : 0.0)                                                           // rsid_rt_bear_norm
array.set(_x, 39, rsid_slow_bull ? 1.0 : 0.0)                                                         // rsid_slow_bull_norm
array.set(_x, 40, rsid_slow_bear ? 1.0 : 0.0)                                                         // rsid_slow_bear_norm
array.set(_x, 41, rsid_delayed_peak ? 1.0 : 0.0)                                                      // rsid_delayed_peak_norm
array.set(_x, 42, rsid_delayed_dip ? 1.0 : 0.0)                                                       // rsid_delayed_dip_norm
array.set(_x, 43, oi_roc_norm)                                                                          // oi_roc_norm
array.set(_x, 44, usdt_d_norm)                                                                          // usdt_d_norm
array.set(_x, 45, basis_norm)                                                                           // basis_norm
array.set(_x, 46, cvd_norm)                                                                             // cvd_norm
array.set(_x, 47, btc_gold_norm)                                                                        // btc_gold_norm
array.set(_x, 48, rsi_subtf_norm)                                                                       // rsi_subtf_norm
array.set(_x, 49, bb_pct_b_norm)                                                                        // bb_pct_b_norm
array.set(_x, 50, cvd_norm)                                                                             // cvd_norm
array.set(_x, 51, rvol_norm)                                                                            // rvol_norm
array.set(_x, 52, active1y_norm)                                                                        // active1y_norm
array.set(_x, 53, hr_norm)                                                                              // hr_norm
array.set(_x, 54, sopr_norm)                                                                            // sopr_norm

// Layer 1: 55 → 16
var float[] _h1 = array.new_float(16, 0.0)
for _i = 0 to 15
    float _s1 = array.get(_b1, _i)
    for _j = 0 to 54
        _s1 += array.get(_w1, _i * 55 + _j) * array.get(_x, _j)
    array.set(_h1, _i, f_tanh(_s1))

// Layer 2: 16 → 8
var float[] _h2 = array.new_float(8, 0.0)
for _i = 0 to 7
    float _s2 = array.get(_b2, _i)
    for _j = 0 to 15
        _s2 += array.get(_w2, _i * 16 + _j) * array.get(_h1, _j)
    array.set(_h2, _i, f_tanh(_s2))

// Layer 3: 8 → 1  (output × 1000 to match [-1000, +1000] scale convention)
float _s3 = array.get(_b3, 0)
for _j = 0 to 7
    _s3 += array.get(_w3, _j) * array.get(_h2, _j)
mlp_score = f_tanh(_s3) * 1000.0

regime_score = i_regime_window > 0 ? ta.sma(mlp_score, i_regime_window) : -1000.0

// ─────────────────────────────────────────────────────────────────────────────
// MVRV Macro Regime Classification
// ─────────────────────────────────────────────────────────────────────────────
mvrv_regime = mvrv_zscore < i_mvrv_bear_threshold ? -1 :
              mvrv_zscore >= i_mvrv_bull_threshold  ?  1 : 0

bgcolor(i_mvrv_regime_show and mvrv_regime == -1 ? color.new(color.red,    85) : na, title="Bear Regime")
bgcolor(i_mvrv_regime_show and mvrv_regime ==  0 ? color.new(color.yellow, 80) : na, title="Sideways Regime")
bgcolor(i_mvrv_regime_show and mvrv_regime ==  1 ? color.new(color.green,  85) : na, title="Bull Regime")

plotchar(mvrv_regime, "mvrv_regime", color=color.gray, display=display.data_window)

plot(mlp_score, "mlp_score", color=color.new(color.gray, 0), linewidth=2)
plot(i_long_exit_activation_confirmation_threshold, "long_exit_confirmation_threshold", color=color.new(color.gray, 20), style=plot.style_line, linewidth=1)
plot(i_long_exit_activation_threshold, title="long_exit_threshold", color=color.new(color.fuchsia, 20), style=plot.style_line, linewidth=1)
plot(i_long_entry_activation_threshold, title="long_entry_threshold", color=color.new(color.blue, 20), style=plot.style_line, linewidth=1)

// ── FEATURE EXPORTS (49 columns; Python reads these for training data + parity) ──────────────
// MLP uses window=1 for RSID signals (raw single-bar flags; no i_div_window extension).
// Cols 3/6/10 (macd_bullish_norm/rsid_norm/stoch_bot_norm) were absent in perceptron Pine
// plotchar exports; restored here to full values since MLP Pine has fresh plot budget.
plotchar((stoch_value - 50.0) / 50.0,                                                                     title="stoch_norm",        color=color.white, display=display.data_window)
plotchar(macd_prediction > 0.0 ? 1.0 : -1.0,                                                             title="macd_pred_norm",    color=color.white, display=display.data_window)
plotchar((osc_1D - 50.0) / 50.0,                                                                           title="osc_norm",           color=color.white, display=display.data_window)
plotchar(macd_flipped_bullish ? 1.0 : 0.0,                                                               title="macd_bullish_norm",  color=color.white, display=display.data_window)
plotchar(m3_momentum > 0.0 ? 1.0 : -1.0,                                                                 title="m3_momentum_norm",  color=color.white, display=display.data_window)
plotchar(m2_diff_abs_tinyOffset_to_future > 1e-9 ? 1.0 : (m2_diff_abs_tinyOffset_to_future < -1e-9 ? -1.0 : 0.0), title="m2_tiny_norm",      color=color.white, display=display.data_window)
plotchar((rsi - 50.0) / 50.0,                                                                             title="rsid_norm",          color=color.white, display=display.data_window)
plotchar(stoch_div_osc > 0.0 ? 1.0 : (stoch_div_osc < 0.0 ? -1.0 : 0.0),                              title="stoch_div_norm",    color=color.white, display=display.data_window)
plotchar(math.max(-1.0, math.min(1.0, vwap_div_osc)),                                                    title="vwap_div_norm",     color=color.white, display=display.data_window)
// stoch_peak_norm MUST stay exported: stoch_is_peaking is the exit condition gate (not just a score weight)
plotchar(stoch_is_peaking ? -1.0 : 0.0,                                                                   title="stoch_peak_norm",   color=color.white, display=display.data_window)
plotchar(stoch_is_bottoming ? 1.0 : 0.0,                                                                  title="stoch_bot_norm",    color=color.white, display=display.data_window)
plotchar(m3_div_osc > 0.0 ? 1.0 : (m3_div_osc < 0.0 ? -1.0 : 0.0),                                    title="m3_div_norm",       color=color.white, display=display.data_window)
plotchar(bearish_engulfing_score,  title="bearish_engulfing_score",  color=color.white, display=display.data_window)
plotchar(m2_div_osc_noOffset > 0.0 ? 1.0 : (m2_div_osc_noOffset < 0.0 ? -1.0 : 0.0),                  title="m2_nooff_norm",     color=color.white, display=display.data_window)
plotchar(m2_div_osc_tiny > 0.0 ? 1.0 : (m2_div_osc_tiny < 0.0 ? -1.0 : 0.0),                          title="m2_div_norm",       color=color.white, display=display.data_window)
plotchar(bullish_hammer_score,     title="bullish_hammer_score",     color=color.white, display=display.data_window)
plotchar(bullish_engulfing_score,  title="bullish_engulfing_score",  color=color.white, display=display.data_window)
plotchar(shooting_star_score,      title="shooting_star_score",      color=color.white, display=display.data_window)
plotchar(rsid_reg_bull      ? 1.0 : 0.0, title="rsid_reg_bull_norm",    color=color.white, display=display.data_window)
plotchar(rsid_reg_bear      ? 1.0 : 0.0, title="rsid_reg_bear_norm",    color=color.white, display=display.data_window)
plotchar(rsid_hid_bull      ? 1.0 : 0.0, title="rsid_hid_bull_norm",    color=color.white, display=display.data_window)
plotchar(rsid_hid_bear      ? 1.0 : 0.0, title="rsid_hid_bear_norm",    color=color.white, display=display.data_window)
plotchar(rsid_rt_bull       ? 1.0 : 0.0, title="rsid_rt_bull_norm",     color=color.white, display=display.data_window)
plotchar(rsid_rt_bear       ? 1.0 : 0.0, title="rsid_rt_bear_norm",     color=color.white, display=display.data_window)
plotchar(rsid_slow_bull     ? 1.0 : 0.0, title="rsid_slow_bull_norm",   color=color.white, display=display.data_window)
plotchar(rsid_slow_bear     ? 1.0 : 0.0, title="rsid_slow_bear_norm",   color=color.white, display=display.data_window)
plotchar(rsid_delayed_peak  ? 1.0 : 0.0, title="rsid_delayed_peak_norm",color=color.white, display=display.data_window)
plotchar(rsid_delayed_dip   ? 1.0 : 0.0, title="rsid_delayed_dip_norm", color=color.white, display=display.data_window)
plotchar(oi_roc_norm,  title="oi_roc_norm",  color=color.white, display=display.data_window)
plotchar(usdt_d_norm,  title="usdt_d_norm",  color=color.white, display=display.data_window)
plotchar(basis_norm,   title="basis_norm",   color=color.white, display=display.data_window)
plotchar(cvd_norm,              title="cvd_norm",              color=color.white, display=display.data_window)
plotchar(btc_gold_norm,         title="btc_gold_norm",         color=color.white, display=display.data_window)
plotchar(rsi_subtf_norm,        title="rsi_subtf_norm",        color=color.white, display=display.data_window)
plotchar(bb_pct_b_norm,         title="bb_pct_b_norm",         color=color.white, display=display.data_window)
// ── MACRO / CROSS-ASSET EXPORTS ───────────────────────────────────────────────────────────────
plotchar(btc_spx_corr_30,    title="btc_spx_corr_30",    color=color.gray, display=display.data_window)
plotchar(dxy_roc_norm,        title="dxy_roc_norm",        color=color.gray, display=display.data_window)
plotchar(vix_pctrank_inv,     title="vix_pctrank_inv",     color=color.gray, display=display.data_window)
plotchar(btc_dom_roc_sign,    title="btc_dom_roc_sign",    color=color.gray, display=display.data_window)
plotchar(us10y_roc_inv_sign,  title="us10y_roc_inv_sign",  color=color.gray, display=display.data_window)
plotchar(us2y_roc_inv_sign,   title="us2y_roc_inv_sign",   color=color.gray, display=display.data_window)
plotchar(yield_curve_sign,    title="yield_curve_sign",    color=color.gray, display=display.data_window)
plotchar(sopr_norm,           title="sopr_norm",           color=color.gray, display=display.data_window)
plotchar(spy_above_200ema,    title="spy_above_200ema",    color=color.gray, display=display.data_window)
plotchar(gold_roc_pctrank,    title="gold_roc_pctrank",    color=color.gray, display=display.data_window)
plotchar(mvrv_zscore_value,   title="mvrv_zscore_value",   color=color.gray, display=display.data_window)
plotchar(mvrv_zscore,         title="zscore",               color=color.gray, display=display.data_window)
plotchar(math.min(1.0, math.max(-1.0, mvrv_zscore / 50.0 - 1.0)), title="mvrv_zscore_cont", color=color.gray, display=display.data_window)
plotchar(nupl_norm,           title="nupl_norm",            color=color.gray, display=display.data_window)
plotchar(fed_net_liq_sign,   title="fed_net_liq_sign",     color=color.gray, display=display.data_window)



// Strategy Logic
// Smoothed exit score — i_exit_score_window=1 is identity (no smoothing).
float mlp_score_exit = i_exit_score_window > 1 ? ta.sma(mlp_score, i_exit_score_window) : mlp_score

// Smoothed entry score — i_entry_score_window=1 is identity (no smoothing).
// No dead-zone guard needed: if SMA is below entry_thr, entry waits for next crossunder (missed trade, not locked position).
float mlp_score_entry = i_entry_score_window > 1 ? ta.sma(mlp_score, i_entry_score_window) : mlp_score

// Dead-zone guard: if a trade enters while the SMA is already below the exit
// threshold, the smoothed crossunder can never fire (there is no ≥→< transition).
// We detect this on the fill bar (position_size goes 0→positive) and switch to
// the raw-score crossunder for the duration of that trade.
var bool _dz_in_pos = false
if strategy.position_size[1] <= 0 and strategy.position_size > 0
    _dz_in_pos := i_exit_score_window > 1 and mlp_score_exit[1] < i_long_exit_activation_threshold
else if strategy.position_size <= 0
    _dz_in_pos := false

// Crossunder signals — smoothed (normal) or raw (dead-zone fallback)
bool _xu_smooth = ta.crossunder(mlp_score_exit[1], i_long_exit_activation_threshold)
bool _xu_raw    = ta.crossunder(mlp_score[1],      i_long_exit_activation_threshold)
bool _xu        = _dz_in_pos ? _xu_raw : _xu_smooth
// Confirmation score: use raw when in dead-zone so all three conditions are consistent
float _exit_score_conf = _dz_in_pos ? mlp_score : mlp_score_exit

longExitCondition = false
if i_use_long_exit_confirmation
    longExitCondition := _xu and _exit_score_conf < i_long_exit_activation_confirmation_threshold
else
    // ⚠ stoch_is_peaking is a CONDITION GATE — not just a score weight.
    // plotchar(stoch_peak_norm) MUST stay exported so Python can replicate this gate.
    longExitCondition := _xu and stoch_is_peaking

longCondition = false
if i_use_long_entry_confirmation
    longCondition := ta.crossunder(mlp_score_entry[1], i_long_entry_activation_threshold) and (mlp_score > mlp_score[1]) and not longExitCondition[1]
else
    longCondition := ta.crossunder(mlp_score_entry, i_long_entry_activation_threshold)
longCondition := longCondition and (i_regime_window == 0 or regime_score > i_regime_entry_min_score)
longCondition := longCondition and (not i_mvrv_suppress_bear or mvrv_regime >= 0)

plotchar(i_use_long_entry_confirmation and longCondition, title="Entry (Confirmed)", char="▲", location=location.belowbar, color=color.aqua, size=size.small, display=display.data_window)
plotchar(not i_use_long_entry_confirmation and longCondition, title="Entry (Standard)", char="▲", location=location.belowbar, color=color.green, size=size.small, display=display.data_window)

missedEntry = longCondition and strategy.position_size > 0
plotchar(missedEntry, title="Missed Entry", char="!", location=location.abovebar, color=color.orange, size=size.tiny, display=display.data_window)

if (longCondition and timeCondition)
    strategy.entry("long", strategy.long)

if (longExitCondition and timeCondition)
    strategy.close("long")

// Trailing stop (percentage-based, bar-close evaluated — matches Python simulation)
var float trail_high_price = na
if strategy.position_size > 0
    trail_high_price := (strategy.position_size[1] <= 0) ? strategy.position_avg_price : math.max(trail_high_price, high)
else
    trail_high_price := na

if (i_trailing_stop_threshold > 0 and strategy.position_size > 0 and timeCondition)
    if close <= trail_high_price * (1.0 - i_trailing_stop_threshold / 100.0)
        strategy.close("long")
