{"slug":"open-source-tradingview-optimizer","qid":"surface","label":"surface","post_title":"open-source-tradingview-optimizer","post_url":"/blog/open-source-tradingview-optimizer#q-surface","columns":["fast_ma","sharpe_slow_50","sharpe_slow_100","sharpe_slow_200"],"rows":[{"fast_ma":5,"sharpe_slow_50":0.68,"sharpe_slow_100":0.7,"sharpe_slow_200":0.93},{"fast_ma":10,"sharpe_slow_50":0.7,"sharpe_slow_100":0.83,"sharpe_slow_200":0.84},{"fast_ma":15,"sharpe_slow_50":0.61,"sharpe_slow_100":0.78,"sharpe_slow_200":0.82},{"fast_ma":20,"sharpe_slow_50":0.61,"sharpe_slow_100":0.63,"sharpe_slow_200":0.74},{"fast_ma":25,"sharpe_slow_50":0.57,"sharpe_slow_100":0.46,"sharpe_slow_200":0.78},{"fast_ma":30,"sharpe_slow_50":0.65,"sharpe_slow_100":0.6,"sharpe_slow_200":0.71}],"shape":"ranking","sql":"WITH\n    series AS\n    (\n        SELECT arraySort(r -> r.1, groupArray((date, toFloat64(close)))) AS rows_sorted\n        FROM global_markets.stocks_daily_aggs\n        WHERE ticker = 'SPY'\n          AND date >= '2016-01-04'\n          AND date <= '2025-06-30'\n    ),\n    grid AS\n    (\n        SELECT\n            arrayMap(r -> r.2, rows_sorted) AS px,\n            g.1                             AS fast,\n            g.2                             AS slow\n        FROM series\n        ARRAY JOIN\n        [\n            (5, 50), (5, 100), (5, 150), (5, 200),\n            (10, 50), (10, 100), (10, 150), (10, 200),\n            (15, 50), (15, 100), (15, 150), (15, 200),\n            (20, 50), (20, 100), (20, 150), (20, 200),\n            (25, 50), (25, 100), (25, 150), (25, 200),\n            (30, 50), (30, 100), (30, 150), (30, 200)\n        ] AS g\n    ),\n    scored AS\n    (\n        SELECT\n            fast,\n            slow,\n            arrayAvg(rets)\n                / sqrt(arrayAvg(arrayMap(r -> r * r, rets)) - pow(arrayAvg(rets), 2))\n                * sqrt(252) AS sharpe\n        FROM\n        (\n            SELECT\n                fast,\n                slow,\n                arrayMap(\n                    i -> if(arrayAvg(arraySlice(px, i - fast + 1, fast)) > arrayAvg(arraySlice(px, i - slow + 1, slow)),\n                            px[i + 1] / px[i] - 1,\n                            0.0),\n                    range(200, length(px))\n                ) AS rets\n            FROM grid\n        )\n    )\nSELECT\n    fast                                 AS fast_ma,\n    round(maxIf(sharpe, slow = 50), 2)   AS sharpe_slow_50,\n    round(maxIf(sharpe, slow = 100), 2)  AS sharpe_slow_100,\n    round(maxIf(sharpe, slow = 200), 2)  AS sharpe_slow_200\nFROM scored\nGROUP BY fast\nHAVING countIf(slow = 50) > 0\n   AND countIf(slow = 100) > 0\n   AND countIf(slow = 200) > 0\nORDER BY fast_ma","computed_at":"2026-09-22T14:53:22.654061+00:00","elapsed":0.005899046}