Анализатор и генератор значений для фортунаты
  • HTML 77.8%
  • C# 21.3%
  • CSS 0.5%
  • Dockerfile 0.3%
Find a file
2026-09-10 17:27:10 +03:00
artifacts Фикс бага добавления билета, фикс сохранения даты следующего розыгрыша, описания у параметров 2026-09-10 17:27:10 +03:00
GeneratorAnylizer Фикс бага добавления билета, фикс сохранения даты следующего розыгрыша, описания у параметров 2026-09-10 17:27:10 +03:00
GeneratorAnylizer.Tests - __Два отдельных контроля в бэктесте:__ независимые случайные билеты и портфель с покрытием, но без исторических предпочтений. 2026-09-08 06:16:52 +03:00
.dockerignore First 2026-08-15 10:18:15 +03:00
.gitignore Подготовка к развёртке 2026-08-25 21:57:36 +03:00
chat-extract.txt First 2026-08-15 10:18:15 +03:00
docker-compose.yml Fixed with Astra 2026-09-07 18:52:44 +03:00
GeneratorAnylizer.slnx First 2026-08-15 10:18:15 +03:00
README.md - __Два отдельных контроля в бэктесте:__ независимые случайные билеты и портфель с покрытием, но без исторических предпочтений. 2026-09-08 06:16:52 +03:00
shared-chat.html First 2026-08-15 10:18:15 +03:00

Fortunata Analyzer

Statistical diagnostics: stage 2

  • Main frequency chi-square statistic is calibrated against 4000 complete independent histories of 7 distinct numbers from 35, not chi-square(34).
  • Bonus frequency and concentration, parity buckets, and two-sided mean sum use Monte Carlo calibration.
  • Fixed overlap lags 1, 2, 3 are tested; lag means distance between recorded draws, not days. Missing records limit interpretation.
  • At 20+ draws, a two-sided label-permutation test compares frequency correlations between the two history halves.
  • Holm correction covers all 8 (or 9) diagnostic hypotheses, before rounding p-values. It permits dependent tests but does not protect repeated inspection or retrospective hypothesis selection.
  • Simulations use fixed seeds and p=(extreme+1)/(B+1). For B=4000 the minimum p is about 0.00025; Monte Carlo standard error near p=0.05 is about 0.0034. Borderline results are not stable evidence.

Backtest uncertainty

Recommendations for draw k+1 use only draws 1..k and a fixed seed. Bootstrap resamples entire draw clusters (10000 replicates), not individual tickets. Duplicating tickets within a draw cannot narrow the interval. There are descriptive 95% intervals for mean matches and share with at least 3 matches, plus separate Bonferroni-adjusted mean intervals across strategies. Fewer than 20 evaluation draws or zero observed variation produces no interval, not zero uncertainty.

Percentile bootstrap coverage is approximate and assumes independent clusters. Serial dependence, regime changes and retrospective tuning can invalidate it. Per-number Wilson intervals and share intervals are descriptive, without multiple-testing correction. Random is an internal strategy with structure/coverage selection, not an independent random control.

Recommendation weights and limitations

History influence is a heuristic max(0, 1 - E[chi2]/chi2), with E[chi2]=28 for main numbers and 53 for bonus. This is neither a formal James-Stein estimator nor a proven signal fraction. Positive weights can occur on fair data. The generator does not enable or disable weights based directly on diagnostic rejection flags.

A rejection does not identify the RNG or establish a predictive advantage. Non-rejection does not prove randomness; around 50 draws provide little power against weak biases. Old numerical conclusions based on chi-square(34) and ticket-independent z-scores are obsolete.

Existing payout/EV calculations were not changed: the static prize table remains unreliable when prize rules vary by date.

Run the console invariant suite with dotnet run --project GeneratorAnylizer.Tests. For the current history use dotnet run --project GeneratorAnylizer.Tests -- --report GeneratorAnylizer/App_Data/draws.json. Tests cover fair/biased histories, fixed periodic dependence, Monte Carlo calibration, reproducibility, short histories and cluster-duplication invariance.

Stage 3: controls and prospective journal

Diagnostics now compares the entire generated portfolio against two equal-sized controls on the same evaluation draws: independently sampled uniform tickets (no selection or deduplication), and the same candidate-selection/coverage algorithm with no history (uniform weights, fixed sum 126, fixed parity target 3). Independent random streams are seeded reproducibly. The primary metric is mean main-number matches per ticket; paired draw differences use 97.5% percentile bootstrap intervals (two-comparison Bonferroni family). This exploratory family is separate from diagnostic Holm tests and per-strategy intervals, not a global 5% guarantee across the whole page.

/Experiment registers virtual portfolios before a future draw, without purchasing tickets. The first POST freezes the horizon (201000 evaluation draws, chosen by the user) and default settings (20 tickets, influence 0.5, randomness 0.2, overlap 2). There is no outcome-driven interim inference: intervals appear only at the planned final count. Positive differences favour the generator; these approximate intervals are not a proof of future profit. The no-history control retains structure preferences, so this is an ablation of history, not pure coverage alone.

The append-only application interface writes App_Data/experiment.json atomically under a single-process lock. Each entry stores UTC creation time, target date, seed, exact training snapshot/hash and all three portfolios. No same-day/past registration, reroll, out-of-order target or second pending entry is allowed. One draw per date is required. The protocol and assembly module ID are frozen: a changed build cannot continue the journal. Preserve the original deployed build, runtime and journal backup. Do not delete the journal to restart after an unfavourable result.

The app does not know the official schedule: register every eligible draw consecutively yourself. This is not an externally trusted timestamp or tamper-proof database; server clock, history and JSON can be edited. Publish the export before each draw for independent timestamping. Protect these routes with the same deployment access controls as the rest of the app. A changed training history is flagged and suppresses final inference. No experiment is started automatically during deployment or tests.

Simulation commands (console test executable):

dotnet run --project GeneratorAnylizer.Tests -- --calibrate 80 30
dotnet run --project GeneratorAnylizer.Tests -- --power 0.30

Calibration reruns the entire adaptive paired-portfolio backtest on independent fair histories, not just resampling a fixed ticket set. Arguments are histories and evaluation draws (plus 10 training draws). It reports the fraction with either false paired deviation and Monte Carlo sampling error; small ensembles are smoke checks, not validation of nominal 5% coverage. This can be slow and does not validate all other tests on the diagnostics page.

Power uses a stated alternative: number 1 is included with probability q, and the remaining six or seven numbers are uniform from 2..35 (q=0.20 is the fair null). It estimates detection by the global main-frequency test at 53, 100, 250 and 500 draws, using 4000 null simulations and 1000 alternative histories, at conservative alpha=0.05/9. Reported standard error is conditional on the simulated null reference; it excludes uncertainty in that reference. This is not power to demonstrate a profitable recommendation strategy or a guaranteed required sample size. Larger ensembles and alternative bias models are needed for precise planning.

Validation snapshot (2026-09-07)

  • Build and console invariants passed, including deterministic controls independent of training history, signed paired effects, registration persistence/concurrency, frozen horizon, history-change detection, suppression of interim inference and final analysis at the planned count. NuGet audit emitted NU1900 because the configured package source was unavailable.
  • HTTP checks on an isolated temporary data directory passed: empty and populated experiment pages, diagnostics rendering, valid registration, export, duplicate rejection and HTTP 400 for POST without an antiforgery token. Real history, purchased tickets and payouts were not changed; no real experiment journal was created.
  • Full paired-backtest calibration: 4 of 80 independent fair histories, each with 10 training and 30 evaluation draws, had either false deviation (5%, estimated Monte Carlo SE 2.44 percentage points). A separate 20-history/20-window smoke run had 2 deviations. These are limited calibration checks, not a proof of nominal coverage.
  • On the current 53-draw history (43 evaluation windows), generator minus independent mean matches was +0.0767, adjusted interval [-0.0140, +0.1651]; generator minus no-history was +0.0570, interval [-0.0058, +0.1221]. Both include zero. These retrospective comparisons do not establish advantage.
  • Under the stated q=0.30 alternative, estimated frequency-test detection rates were 1.7%, 5.0%, 22.2%, 65.0% for 53, 100, 250, 500 draws respectively. With q=0.20 (fair null), rejection rates were 0.2%, 0.8%, 0.8%, 0.5%, around the conservative 0.556% threshold with simulation error. Do not interpret these rates as probabilities of winning.

Deployment on Raspberry Pi 5

Приложение рассчитано на один экземпляр контейнера и хранит пользовательские данные в JSON-файлах.

Persistent data

В docker-compose.yml подключён bind mount:

./data:/app/App_Data

На сервере рядом с docker-compose.yml будут храниться:

data/draws.json
data/purchased-tickets.json

При первом запуске entrypoint копирует исходный draws.json в пустую data/. Уже существующие файлы не перезаписываются. Каталог data/ исключён из Git, поэтому его нужно резервировать отдельно.

Контейнер запускается с правом записи в bind mount, потому что Docker на Raspberry Pi обычно создаёт новую папку data/ от root. Порт приложения ограничен 127.0.0.1, а внешний доступ отдаётся только через Nginx.

Deploy from Forgejo checkout

На Raspberry Pi 5 (64-bit Raspberry Pi OS):

git clone https://forgejo.example.com/<user>/GeneratorAnylizer.git
cd GeneratorAnylizer
docker compose up -d --build
docker compose logs -f generator-analyzer

Приложение не публикует порт на хост вообще. Оно доступно только контейнеру Nginx через общую Docker-сеть reverse-proxy.

После обновления из Forgejo:

git pull
docker compose up -d --build

Перед обновлением сделайте резервную копию:

tar -czf fortunata-data-$(date +%F).tar.gz data/

Portainer

В Portainer откройте Stacks → Add stack → Repository и укажите Forgejo-репозиторий. В качестве compose path используйте docker-compose.yml. Для приватного Forgejo-репозитория добавьте registry/repository credentials или deploy key. Рабочая директория стека содержит bind mount ./data, поэтому не удаляйте её при обновлении стека.

Nginx

Nginx-конфигурация намеренно хранится в отдельном infrastructure-репозитории Deployment: nginx/templates/prod/fortunata-analyzer.conf.template. Она проксирует в контейнер generator-analyzer:8080 через общую внешнюю Docker-сеть reverse-proxy.

До первого запуска обоих stack на Raspberry Pi один раз создайте сеть:

docker network create reverse-proxy

Приложение принимает X-Forwarded-Proto, поэтому при HTTPS-терминации на Nginx не возникает цикл HTTPS-редиректов.

ARM64

Официальные образы mcr.microsoft.com/dotnet/aspnet:10.0 и mcr.microsoft.com/dotnet/sdk:10.0 являются multi-architecture. На Raspberry Pi 5 с 64-bit ОС Docker автоматически соберёт ARM64-образ. Не задавайте platform: linux/amd64.

Limitation

JSON-хранилище подходит для одного пользователя и одной реплики контейнера. Не запускайте несколько реплик с одной папкой data/.