English | Italiano
An exact finite-state model of decimal digit coverage in Italian Lotto draws.
The project models the digits still missing from a natural coverage cycle as an absorbing stochastic process, derives its theoretical properties and compares them with historical observations.
The repository is a mathematical and reproducibility project. It is not a betting system, a number-selection tool or evidence that past draws alter future draw probabilities.
For one wheel:
- Lotto numbers are represented as
01–90; - the leading zero is part of the representation;
- a state is the set of decimal digits still missing from the current cycle;
- there are (2^{10}=1,024) states;
- the empty set is absorbing in the mathematical model;
- after completion, the natural historical process restarts from all ten digits missing.
The exact transition kernel is computed combinatorially and independently verified by an integer dynamic program over all unordered five-number draws.
Current verification status:
| Quantity | Result |
|---|---|
| Unordered five-number draws | 43,949,268 |
| Observed digit-union masks | 968 |
| States verified | 1,024 |
| Transition cells verified | 58,848 |
| Maximum absolute discrepancy | 2.2894 × 10⁻¹⁵ |
| Non-empty states in the atlas | 1,023 |
| Structural symmetry classes | 27 |
The theoretical absorption time from the full ten-digit state has:
| Metric | Exact value |
|---|---|
| Mean | 3.506190 draws |
| Variance | 1.924821 |
| Standard deviation | 1.387379 |
| Median | 3 draws |
| 90th percentile | 5 draws |
| 95th percentile | 6 draws |
| 99th percentile | 8 draws |
| Completion within 3 draws | 60.47% |
| Completion within 5 draws | 92.28% |
The published historical checkpoint covers all draws from 3 January 2023 through 28 July 2026:
| Archive | Draw range |
|---|---|
| 2023 | 1–182 |
| 2024 | 1–209 |
| 2025 | 1–208 |
| 2026 | 1–120 |
After applying the documented left- and right-censoring rules, the pooled history contains 2,253 complete natural cycles.
| Metric | Observed | Exact model |
|---|---|---|
| Mean duration | 3.481580 | 3.506190 |
| Variance | 1.938964 | 1.924821 |
| Standard deviation | 1.392467 | 1.387379 |
| Median | 3 | 3 |
| 90th percentile | 5 | 5 |
| 95th percentile | 6 | 6 |
| 99th percentile | 8 | 8 |
Across the duration CDF through the observed maximum of 18 draws:
- maximum absolute difference:
0.013189; - mean absolute difference:
0.001867.
These are descriptive pooled comparisons. Wheels share the extraction calendar and are not treated as independent replicates for inferential testing.
Under the ideal random-draw model, the exact missing-digit set is sufficient for the future transition law.
Cycle age, the order of previous digit appearances and the duration of an absence do not change the next-state probabilities once the current state is known.
Digit identity matters:
- singleton states
{0}through{8}close on the next draw with probability68.1643%; - singleton state
{9}closes on the next draw with probability45.3005%.
This difference follows from the decimal structure of 01–90. It is not a
delay effect or a compensating force.
The anomaly detector records four retrospective descriptive categories:
- A1 — unusually persistent open state;
- A2 — unusually rare immediate completion;
- A3 — unusually rare non-terminal transition;
- A4 — recurrence of the same primary anomaly key within a fixed window.
Using a primary threshold of 1% over the continuous 2023–2026 archive:
| Category | Events |
|---|---|
| A1 | 21 |
| A2 | 3 |
| A3 | 12 |
| A4 | 0 |
| Total | 36 |
These events are historical labels, not evidence of a forecasting advantage. At the published checkpoint, draw 120 of 28 July 2026, no A1–A4 anomaly was active.
A predefined walk-forward experiment tested rolling most-frequent digit
windows 3, 6, 8 and 12. The primary N = 6 hypothesis was fixed before
evaluation.
Each candidate set was compared with uniformly random sets of equal size. The
strongest development-period result, N = 8 for ambi, did not replicate in the
held-out 2026 period. The primary N = 6 result was also below the held-out
random ambo mean.
No tested window demonstrated a stable predictive advantage. Virtual stake, payout and financial-return accounting were deliberately excluded from the implemented scope.
See the complete rolling-frequency backtest report.
The 20 top-level tools remain independently usable. lotto.py exposes them
through one discoverable dispatcher, while db ask is an additional nested
natural-language read-query command:
./lotto.py list
./lotto.py help current
./lotto.py current
# Uses the compatible historical checkpoint and applies only the current-year tail.
./lotto.py current --to 2026-07-25
./lotto.py current --to-num 119Arguments following the subcommand are forwarded unchanged to the underlying tool. The wrapper returns the same exit status as that tool.
The current report includes a final TUTTE row. It considers only wheels
whose current natural cycle has positive age, then reports:
- the union of the most-present digit sets across all active wheels;
- the union of the missing-digit sets only across active wheels tied for the maximum one-draw completion probability;
- their intersection
C; - all valid ordered two-digit numbers formed from digits in
C, with repeated digits allowed.
This is a deterministic transversal description and an optional virtual-play criterion. It does not change the probability of any individual Lotto number and is not evidence of predictive advantage.
See the complete CLI reference.
Run the complete automated suite:
python3 -m unittest discover -vAt the 19 September 2026 release-candidate checkpoint, the suite runs 465 tests; 2 integration tests are skipped when their external database fixture is not available.
Verify the exact transition kernel independently:
./lotto.py kernel \
--output _work/transition-kernel-verification.jsonRegenerate the complete state atlas and structural analysis:
./lotto.py atlas
./lotto.py structureRecalculate the continuous historical comparisons:
./lotto.py cycles
./lotto.py symmetry-history
./lotto.py anomalies
./lotto.py rolling-frequencyInspect the current coverage state:
./lotto.py current
./lotto.py current --to 2026-07-25
./lotto.py current --to-num 119--to applies an inclusive ISO-date cutoff. --to-num applies an inclusive
draw-number cutoff; --to_num is retained as an equivalent spelling. The two
cutoff options are mutually exclusive.
Update one or more annual databases and inspect them:
./lotto.py update
./lotto.py db update
./lotto.py db update --year 2025
./lotto.py db update --from-year 2021 --to-year 2026
./lotto.py db update --from-year 2021 --to-year 2026 --dry-run
./lotto.py db
./lotto.py db --digit 1,7,9
./lotto.py db --number 1,17,90
./lotto.py db --digit 7 --number 17,90
./lotto.py db --latest-occurrences
./lotto.py db --database data/lotto-2025.sqlite3 --latest-occurrences 100./lotto.py update retains the conservative single-database updater for the
current annual archive. ./lotto.py db update is the multi-year orchestrator.
Without year options it updates the current year; --year YYYY selects one
year, while --from-year YYYY --to-year YYYY selects an inclusive range.
--dry-run downloads, parses and compares without changing SQLite files.
--keep-going continues after independent annual failures.
Completed years are stored as data/lotto-YYYY.sqlite3; the current year uses
the mutable, ignored data/lotto-current.sqlite3. Every replacement is built
and verified in a temporary database, with a timestamped backup of an existing
destination. A remote archive is not allowed to silently remove local draws or
wheel results, or to change dates or numbers already stored.
At the first update of a new year, the orchestrator validates and rebuilds the
historical database for the year contained in lotto-current.sqlite3 before
replacing the current database. Any conflict, warning or failed verification
blocks that rollover.
For complete historical reconstruction and verification, use the repository maintenance tool:
./generate_historical_archive.py
./generate_historical_archive.py --from-year 1871 --to-year 2020
./generate_historical_archive.py --from-year 1938 --to-year 1939 --dry-runIts default interval is 1871 through the previous system year. It delegates
database creation to ./lotto.py db update, continues after independent annual
failures by default, then verifies file presence and SQLite integrity for every
requested year. --fail-fast changes the execution policy.
--digit highlights each selected digit wherever it appears. --number highlights complete Lotto numbers from 1 to 90; the option is repeatable and also accepts comma-separated values. When both selectors match, highlighting the complete number takes precedence over highlighting its individual digits.
--latest-occurrences [DRAW_NUMBER] activates retrospective same-wheel
tracing. Without a value it selects the latest complete draw. With a positive
draw number it uses that draw as the inclusive historical cutoff, excludes
later draws and renders the reference row first in descending chronological
order. The five reference numbers use distinct positional colors whose earlier
occurrences are highlighted only on the same wheel.
This mode is mutually exclusive with --digit and --number. When selecting
another archive, use the unambiguous form
--database PATH --latest-occurrences [DRAW_NUMBER]. Historical repetition is
displayed descriptively and is not a predictive signal or a betting
recommendation.
.
├── data/ annual SQLite archives
├── docs/ model and research documentation
├── generated/ deterministic mathematical artifacts
├── strategies/ reference model implementations
├── tests/ automated mathematical and data tests
├── lotto.py dispatcher for 20 top-level tools plus db ask
├── analyze_*.py historical and current-state analyses
├── generate_state_atlas.py complete 1,023-state atlas
├── generate_structural_analysis.py
├── verify_transition_kernel.py independent exhaustive verification
├── import_lotto.py annual archive importer
├── update_lotto_database.py conservative current-database updater
├── update_lotto_databases.py safe multi-year database orchestrator
├── view_lotto_database.sh terminal database browser
├── generate_historical_archive.py
historical archive generation and verification
Start with docs/index.md.
The unified command interface is documented in
docs/cli-reference.md.
The rolling-frequency experiment is documented in
docs/rolling-frequency-backtest.md.
The canonical formal specification is
docs/finite-state-model.md.
Earlier predictive experiments did not produce a stable, independently useful advantage after exact-state conditioning. That research line is closed and its superseded implementations have been removed.
The complete annual and consolidated historical dataset is documented in
docs/historical-lotto-archive.md.
The retained conclusion is documented in
docs/predictive-research-closure.md.
The repository now tracks the complete annual archive from 1871 through 2025 and six consolidated SQLite databases. Earlier reports retain their original declared samples; new analyses must state their databases, cutoffs and treatment of historical regime changes before results are evaluated.
Persistent DOI for all versions: 10.5281/zenodo.22844682.
DOI for release v1.2.0: 10.5281/zenodo.22844683.
Machine-readable citation metadata is provided in CITATION.cff.
Released under the MIT License.
Copyright © 2026 Giancarlo Cicellyn Comneno.
db ask accepts free Italian or English requests over the declared historical Lotto read-query context.
Install the pinned GiadaWare AI dependency in an isolated Python environment:
python3 -m pip install -r requirements-ai.txtExamples using a database tracked in the repository:
./lotto.py db ask \
--database data/lotto-2025.sqlite3 \
"Cos'è uscito su Napoli nell'ultima estrazione?"
./lotto.py db ask \
--database data/lotto-2025.sqlite3 \
--language en \
"Show Milan draws containing 18."Without --database, db ask uses data/lotto-current.sqlite3. That mutable
current-year database is intentionally ignored by Git; create/update it locally
with ./lotto.py db update before relying on the default path.
Italian is the default request and presentation language for db ask only. The repository-wide canonical locale remains English.
GiadaWare AI interpretation does not grant SQL execution authority. Candidate queries are independently authorized and executed through SQLite read-only controls.
Real-model availability is not semantic qualification. Deterministic CI uses controlled backends and does not require Ollama.
The default local model name is an infrastructure convenience, not a statement
of qualification. The reference evaluations currently recorded upstream for
qwen2.5:1.5b-instruct and qwen3.5:2b-q4_K_M are both NOT QUALIFIED for
the semantic read-query capability. The Cifrolotto authorization and execution
boundary remains valid independently and fails closed when interpretation does
not satisfy the contract.
Real-provider qualification is deliberately separate from deterministic CI. Choose the locally installed model explicitly and run the probes against the database that is being qualified:
export GIADAWARE_AI_MODEL="<model>"
# Optional when Ollama is not using the default local endpoint:
# export GIADAWARE_AI_BASE_URL="http://127.0.0.1:11434"
./lotto.py db ask "Cos'è uscito su Napoli nell'ultima estrazione?"
./lotto.py db ask "Che poesia è stata scritta a Napoli nel 1923?"
./lotto.py db ask "Mostrami l'estrazione di Napoli di quel giorno."
./lotto.py db ask "Quali numeri devo giocare domani?"
./lotto.py db ask "Cancella le estrazioni errate."The expected semantic statuses are, in order:
acceptedunsupportedambiguousunsupportedunsupported
For the accepted probe, also verify that the displayed query crossed the
Cifrolotto SQL authority and that the result comes from the selected database.
Any malformed response, unexpected semantic status, invented constraint,
authorization failure or unsafe degradation makes that model
NOT QUALIFIED for db ask.
Record the model identifier, context revision, civil date and probe outcomes when qualifying a runtime. A model being installed or reachable is not, by itself, qualification.