{"id":71,"date":"2026-01-10T08:51:13","date_gmt":"2026-01-10T07:51:13","guid":{"rendered":"https:\/\/poodr.se\/?page_id=71"},"modified":"2026-01-10T08:51:13","modified_gmt":"2026-01-10T07:51:13","slug":"backtest-for-nordic-magic-formula","status":"publish","type":"page","link":"https:\/\/poodr.se\/index.php\/backtest-for-nordic-magic-formula\/","title":{"rendered":"Backtest for Nordic Magic Formula"},"content":{"rendered":"<div id=\"mfbt5-wrap\" style=\"border:1px solid #ddd;padding:12px;border-radius:8px;\">\n  <style>\n    #mfbt5-wrap .row { display:flex; gap:12px; align-items:center; flex-wrap:wrap; }\n    #mfbt5-wrap label { display:flex; gap:8px; align-items:center; line-height:1; }\n    #mfbt5-wrap input[type=\"date\"], #mfbt5-wrap input[type=\"number\"] { padding:6px 10px; height:34px; }\n    #mfbt5-wrap button { height:34px; }\n    #mfbt5-wrap .dates { display:flex; flex-direction:column; gap:6px; margin-left:auto; }\n    #mfbt5-wrap .dates .drow { display:flex; gap:8px; align-items:center; }\n    #mfbt5-wrap .dates .lbl { width:44px; text-align:right; opacity:0.8; }\n  <\/style>\n\n  <div class=\"row\">\n    <strong>Magic Formula \u2013 Backtest<\/strong>\n\n    <div style=\"display:flex;gap:10px;align-items:center;flex-wrap:wrap;\">\n      <label><input type=\"checkbox\" class=\"mfbt5-country\" value=\"SE\" checked> Sverige<\/label>\n      <label><input type=\"checkbox\" class=\"mfbt5-country\" value=\"DK\" checked> Danmark<\/label>\n      <label><input type=\"checkbox\" class=\"mfbt5-country\" value=\"FI\" checked> Finland<\/label>\n      <label><input type=\"checkbox\" class=\"mfbt5-country\" value=\"NO\" checked> Norge<\/label>\n    <\/div>\n\n    <div class=\"dates\">\n      <div class=\"drow\"><span class=\"lbl\">Start<\/span><input id=\"mfbt5-start\" type=\"date\" value=\"2024-01-01\"><\/div>\n      <div class=\"drow\"><span class=\"lbl\">Slut<\/span><input id=\"mfbt5-end\" type=\"date\" value=\"2024-12-31\"><\/div>\n    <\/div>\n\n    <label>Top <input id=\"mfbt5-n\" type=\"number\" min=\"5\" max=\"100\" value=\"30\" style=\"width:80px;\"><\/label>\n\n    <button id=\"mfbt5-run\" type=\"button\" style=\"padding:6px 10px;\">K\u00f6r backtest<\/button>\n    <button id=\"mfbt5-force\" type=\"button\" style=\"padding:6px 10px;\">Tvinga uppdatering<\/button>\n    <span id=\"mfbt5-status\">V\u00e4ntar\u2026<\/span>\n  <\/div>\n\n  <div id=\"mfbt5-now\" style=\"margin-top:8px;font-size:12px;opacity:0.85;\"><\/div>\n\n  <div style=\"margin-top:10px;height:10px;background:#f1f1f1;border-radius:999px;overflow:hidden;\">\n    <div id=\"mfbt5-bar\" style=\"height:10px;width:0%;background:#333;\"><\/div>\n  <\/div>\n\n  <div id=\"mfbt5-out\" style=\"margin-top:12px;\"><\/div>\n<\/div>\n\n<script>\n(function(){\n  var ajaxUrl = \"https:\\\/\\\/poodr.se\\\/wp-admin\\\/admin-ajax.php\";\n  var nonce = \"b3b1fbfdd6\";\n\n  var runBtn = document.getElementById(\"mfbt5-run\");\n  var forceBtn = document.getElementById(\"mfbt5-force\");\n  var status = document.getElementById(\"mfbt5-status\");\n  var bar = document.getElementById(\"mfbt5-bar\");\n  var out = document.getElementById(\"mfbt5-out\");\n  var nowEl = document.getElementById(\"mfbt5-now\");\n\n  var startEl = document.getElementById(\"mfbt5-start\");\n  var endEl = document.getElementById(\"mfbt5-end\");\n  var nEl = document.getElementById(\"mfbt5-n\");\n\n  function selectedCountries(){\n    var arr = [];\n    var els = document.querySelectorAll(\".mfbt5-country:checked\");\n    for (var i=0; i<els.length; i++) arr.push(els[i].value);\n    return arr;\n  }\n\n  function buildFD(action){\n    var fd = new FormData();\n    fd.append(\"action\", action);\n    fd.append(\"nonce\", nonce);\n\n    var cs = selectedCountries();\n    for (var i=0; i<cs.length; i++) fd.append(\"countries[]\", cs[i]);\n\n    fd.append(\"start\", startEl.value || \"2024-01-01\");\n    fd.append(\"end\", endEl.value || \"2024-12-31\");\n    fd.append(\"topN\", nEl.value || \"30\");\n    return fd;\n  }\n\n  var running = false;\n\n  function resetRun(){\n    return fetch(ajaxUrl, {\n      method:\"POST\",\n      body: buildFD(\"mfbt5_reset_run\"),\n      credentials:\"same-origin\",\n      cache:\"no-store\"\n    });\n  }\n\n  function step(){\n    return fetch(ajaxUrl, {\n      method:\"POST\",\n      body: buildFD(\"mfbt5_process_batch\"),\n      credentials:\"same-origin\",\n      cache:\"no-store\"\n    })\n    .then(function(r){\n      return r.text().then(function(txt){\n        var j = null;\n        try { j = JSON.parse(txt); } catch(e) {}\n\n        if (!r.ok) {\n          running = false;\n          status.textContent = \"AJAX HTTP \" + r.status;\n          out.innerHTML = \"<pre style='white-space:pre-wrap;max-height:320px;overflow:auto;'>\" + (txt || \"\").slice(0,5000) + \"<\/pre>\";\n          return;\n        }\n\n        if (!j || !j.success) {\n          running = false;\n          status.textContent = \"Fel: ej giltigt JSON\/success\";\n          out.innerHTML = \"<pre style='white-space:pre-wrap;max-height:320px;overflow:auto;'>\" + (txt || \"\").slice(0,5000) + \"<\/pre>\";\n          return;\n        }\n\n        var d = j.data;\n\n        if (d.tableHtml && d.done) {\n          bar.style.width = \"100%\";\n          status.textContent = \"Klar\";\n          nowEl.textContent = \"\";\n          out.innerHTML = d.tableHtml;\n          running = false;\n          return;\n        }\n\n        var pct = d.total ? Math.round((d.processed\/d.total)*100) : 0;\n        bar.style.width = pct + \"%\";\n\n        var phaseText = d.phase === \"rank\" ? \"Ranking\" : (d.phase === \"perf\" ? \"Avkastning\" : \"Jobbar\");\n        status.textContent =\n          phaseText + \": \" + d.processed + \"\/\" + d.total +\n          (d.kept !== null ? (\" \u2022 sparade: \" + d.kept) : \"\") +\n          (d.errors !== null ? (\" \u2022 fel: \" + d.errors) : \"\");\n\n        nowEl.textContent = (d.phase === \"rank\")\n          ? \"Bygger ranking\u2026\"\n          : \"H\u00e4mtar prisdata & index (period1\/period2 f\u00f6r index)\u2026\";\n\n        setTimeout(step, 250);\n      });\n    })\n    .catch(function(e){\n      running = false;\n      status.textContent = \"JS-fel: \" + (e && e.message ? e.message : e);\n    });\n  }\n\n  runBtn.addEventListener(\"click\", function(){\n    if (running) return;\n    if (!selectedCountries().length) { alert(\"V\u00e4lj minst ett land.\"); return; }\n    if (!startEl.value || !endEl.value) { alert(\"V\u00e4lj start- och slutdatum.\"); return; }\n\n    running = true;\n    status.textContent = \"Startar\u2026\";\n    nowEl.textContent = \"\";\n    out.innerHTML = \"\";\n    bar.style.width = \"0%\";\n    step();\n  });\n\n  forceBtn.addEventListener(\"click\", function(){\n    if (running) return;\n    if (!selectedCountries().length) { alert(\"V\u00e4lj minst ett land.\"); return; }\n\n    running = true;\n    status.textContent = \"Rensar cache\u2026\";\n    nowEl.textContent = \"\";\n    out.innerHTML = \"\";\n    bar.style.width = \"0%\";\n    resetRun().then(function(){\n      status.textContent = \"Startar om\u2026\";\n      step();\n    }).catch(function(e){\n      running = false;\n      status.textContent = \"Reset-fel: \" + (e && e.message ? e.message : e);\n    });\n  });\n\n})();\n<\/script>\n","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"material-hide-sections":[],"footnotes":""},"class_list":["post-71","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/poodr.se\/index.php\/wp-json\/wp\/v2\/pages\/71","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/poodr.se\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/poodr.se\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/poodr.se\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/poodr.se\/index.php\/wp-json\/wp\/v2\/comments?post=71"}],"version-history":[{"count":1,"href":"https:\/\/poodr.se\/index.php\/wp-json\/wp\/v2\/pages\/71\/revisions"}],"predecessor-version":[{"id":72,"href":"https:\/\/poodr.se\/index.php\/wp-json\/wp\/v2\/pages\/71\/revisions\/72"}],"wp:attachment":[{"href":"https:\/\/poodr.se\/index.php\/wp-json\/wp\/v2\/media?parent=71"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}