docs(sec): SEC-9 закрыт — возврат залога при ничьей
Сводка: открыто 8 (было 9), закрыто 8. SEC-9 перенесён в закрытые с полной историей: причина (close_bet.rs:66), замер доли ничьих (33.6%), решение владельца (правка контракта), состав правок, собственная мутационная приёмка, деплой и живой эффект (залипшие #0/#1 закрылись сами, ваулт −1000). Хвост SEC-8 о «вечном залипании» помечен как устранённый. Инструменты приёмки: - tie-refund-accept.cjs — ставки циклом, проверка статуса на цепи (живой прогон: 6 возвратов из 25 ставок) - tie-distribution.cjs, policy-economics.cjs — выбор политики ничьей - vault-check.cjs — разбор Bet-аккаунтов сырыми байтами
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
// Полное распределение: тики между входом и выходом 15-сек окна + шаг самого фида.
|
||||
const { DatabaseSync } = require('node:sqlite');
|
||||
const db = new DatabaseSync(process.env.DB || '/app/data/price-history.db');
|
||||
const rows = db.prepare('SELECT ts, price FROM price_history ORDER BY ts ASC').all();
|
||||
const vals = rows.map((r) => ({ ts: Number(r.ts), p: Number(r.price) }));
|
||||
const SCALE = 1e8;
|
||||
console.log('записей:', vals.length, '| диапазон:', (vals[0].p / SCALE).toFixed(2), '→', (vals[vals.length - 1].p / SCALE).toFixed(2));
|
||||
|
||||
// Шаг самого фида: как меняется цена от записи к записи
|
||||
const stepHist = {};
|
||||
let zeroSteps = 0;
|
||||
for (let i = 1; i < vals.length; i++) {
|
||||
const d = Math.round(Math.abs(vals[i].p - vals[i - 1].p) / SCALE * 100); // в сотых
|
||||
stepHist[d] = (stepHist[d] || 0) + 1;
|
||||
if (d === 0) zeroSteps++;
|
||||
}
|
||||
const stepKeys = Object.keys(stepHist).map(Number).sort((a, b) => a - b);
|
||||
console.log('--- шаг фида (от записи к записи, в копейках) ---');
|
||||
for (const k of stepKeys.slice(0, 12)) console.log(` ровно ${k} коп: ${stepHist[k]}`);
|
||||
console.log(' уникальных шагов:', stepKeys.length, '| «без изменений»:', zeroSteps, `(${((100 * zeroSteps) / (vals.length - 1)).toFixed(1)}%)`);
|
||||
|
||||
const at = (ts) => {
|
||||
let lo = 0, hi = vals.length - 1, res = null;
|
||||
while (lo <= hi) {
|
||||
const m = (lo + hi) >> 1;
|
||||
if (vals[m].ts <= ts) { res = vals[m].p; lo = m + 1; } else hi = m - 1;
|
||||
}
|
||||
return res;
|
||||
};
|
||||
|
||||
const W = 15000, STEP = 1000;
|
||||
const hist = {};
|
||||
let n = 0;
|
||||
for (let t = vals[0].ts; t + W <= vals[vals.length - 1].ts; t += STEP) {
|
||||
const a = at(t), b = at(t + W);
|
||||
if (a === null || b === null) continue;
|
||||
const kop = Math.round(Math.abs(b - a) / SCALE * 100);
|
||||
hist[kop] = (hist[kop] || 0) + 1;
|
||||
n++;
|
||||
}
|
||||
const keys = Object.keys(hist).map(Number).sort((a, b) => a - b);
|
||||
console.log('--- окон 15 с проверено:', n, '| уникальных значений |delta|:', keys.length);
|
||||
console.log(' распределение по модулю разницы (копейки):');
|
||||
for (const k of keys.slice(0, 15)) console.log(` |Δ|=${k} коп: ${hist[k]} (${((100 * hist[k]) / n).toFixed(2)}%)`);
|
||||
const tie = hist[0] || 0;
|
||||
console.log(`НИЧЬЯ (|Δ|=0): ${tie} = ${((100 * tie) / n).toFixed(2)}%`);
|
||||
const near = (keys.filter((k) => k > 0 && k <= 5).reduce((s, k) => s + hist[k], 0));
|
||||
console.log(`почти-ничья (|Δ| = 1..5 коп): ${near} = ${((100 * near) / n).toFixed(2)}%`);
|
||||
Reference in New Issue
Block a user