한국어 | English
True random numbers sourced from live cryptocurrency market data.
import coinrandom
coinrandom.random() # 0.7182818...
coinrandom.randint(1, 100) # 42
coinrandom.choice(["a", "b", "c"])Cryptocurrency markets trade 24/7 globally. At the tick level — individual trade prices, quantities, timestamps, and buyer/seller direction — the data is highly unpredictable. The Efficient Market Hypothesis (EMH) says no one can consistently predict short-term market movements. coinrandom uses this unpredictability as an entropy source.
Even with the full source code published, no one can predict the output in advance — because no one can predict the coin market.
This is an application of Kerckhoffs's principle: security depends on the unpredictability of the market, not on keeping the algorithm secret. Every value comes with a RandomProof — a verifiable audit trail showing exactly which market data produced the result.
Honest limits: coinrandom provides computational security (like AES/RSA), not information-theoretic security (like Chainlink VRF). The trust model is economic, not mathematical. For cryptographic key generation, use secrets. For smart contract RNG, use Chainlink VRF.
pip install coinrandom # Standard
pip install "coinrandom[heavy]" # + Heavy (numpy, scipy)No API keys. No configuration.
| Tier | Speed | Entropy source | Proof | Use case |
|---|---|---|---|---|
| Standard (default) | ~2s | 3 exchanges + ETH/BTC/SOL block data + Argon2id | Yes | Raffles, NFT mints, DAO votes |
| Heavy | ~30s | Portfolio-optimized coins + Standard pipeline | Yes | Maximum entropy, auditable |
Both tiers run the full entropy pipeline on every call and return the same API — a drop-in replacement for Python's random module.
| Function | Signature | Description |
|---|---|---|
random() |
() → float |
Uniform float in [0.0, 1.0) |
uniform(a, b) |
(float, float) → float |
Uniform float in [a, b] |
randint(a, b) |
(int, int) → int |
Uniform integer in [a, b] inclusive |
choice(seq) |
(Sequence) → Any |
One random element from a sequence |
choices(seq, k) |
(Sequence, int) → list |
k elements with replacement |
sample(seq, k) |
(Sequence, int) → list |
k elements without replacement |
shuffle(seq) |
(MutableSequence) → None |
In-place shuffle |
gauss(mu, sigma) |
(float, float) → float |
Normal distribution sample |
random_with_proof() |
() → RandomProof |
Value + audit trail (Heavy returns HeavyProof) |
All functions have async variants prefixed with a: arandom(), arandint(), arandom_with_proof(), etc.
Each call fetches live data from 3 exchanges (Binance, Upbit, Coinbase) + ETH/BTC/SOL block data, then applies Argon2id (t=4, m=64MB). Returns a RandomProof with a full audit trail.
import coinrandom
# Basic
coinrandom.random() # 0.7182818... float in [0.0, 1.0)
coinrandom.uniform(1.5, 9.5) # 6.234... float in [a, b]
coinrandom.randint(1, 6) # 4 integer in [a, b] inclusive
coinrandom.gauss(mu=0.0, sigma=1.0) # -0.312... normal distribution
# Sequences
coinrandom.choice(["rock", "paper", "scissors"]) # pick one
coinrandom.choices(range(1, 7), k=5) # roll dice 5 times (with replacement)
coinrandom.sample(range(1, 46), k=6) # lotto numbers (no duplicates)
lst = list(range(1, 11))
coinrandom.shuffle(lst) # in-place shuffle
# Practical: auditable raffle — pick a winner from participants
participants = ["Alice", "Bob", "Carol", "Dave", "Eve"]
proof = coinrandom.random_with_proof()
winner = participants[int(proof.value * len(participants))]
print(winner)
print(proof.value) # 0.3571428...
print(proof.block_hashes) # {"ETH": "0xabc123...", "BTC": "000...", "SOL": "..."}
print(proof.exchanges) # [{"exchange": "binance", "symbol": "BTCUSDT", ...}, ...]
print(proof.symbols) # symbols used as entropy
print(proof.final_hash) # SHA-256 of the Argon2-stretched entropy
print(proof.timestamp) # "2026-06-13T09:00:00.123456+00:00"Runs inverse Markowitz optimization to select the least-correlated coins as entropy sources before executing the Standard pipeline. Requires the [heavy] extra.
from coinrandom import heavy # requires: pip install "coinrandom[heavy]"
val = heavy.random()
proof = heavy.random_with_proof()
print(proof.value)
print(proof.selected_symbols) # coins selected by inverse portfolio optimization
print(proof.candidate_count) # number of candidate coins analyzed
print(proof.correlation_matrix) # correlation matrix of candidates
print(proof.optimization_result) # scipy SLSQP result
print(proof.block_hashes) # {"ETH": "...", "BTC": "...", "SOL": "..."}
print(proof.final_hash)
# Practical: NFT mint order — save proofs so anyone can verify the shuffle
token_ids = list(range(1, 10001))
heavy.shuffle(token_ids)RandomProof and HeavyProof are plain dataclasses — serialize with the standard library:
import dataclasses, json
import coinrandom
proof = coinrandom.random_with_proof()
with open("proof.json", "w") as f:
json.dump(dataclasses.asdict(proof), f, indent=2)All functions have async variants prefixed with a.
import asyncio
import coinrandom
from coinrandom import heavy # heavy requires the [heavy] extra
async def main():
# Standard
val = await coinrandom.arandom()
n = await coinrandom.arandint(1, 100)
c = await coinrandom.achoice(["a", "b", "c"])
lst = [1, 2, 3]
await coinrandom.ashuffle(lst)
proof = await coinrandom.arandom_with_proof()
print(proof.block_hashes)
# Heavy
val = await heavy.arandom()
proof = await heavy.arandom_with_proof()
print(proof.selected_symbols)
asyncio.run(main())Async methods offload blocking I/O to a thread pool via asyncio.run_in_executor — no new dependencies.
- No API keys — works out of the box with
pip install - Uniform API — every tier exposes the same functions as
random - No stdlib random — coin market data + OS hardware entropy mixed with SHA-512, stretched with Argon2id
- Open-source safe — Kerckhoffs's principle: publishing the algorithm doesn't compromise security
- Intentionally heavy — each call runs the full entropy pipeline. "Slow = costly to manipulate."
coinrandom/
├── __init__.py # Standard tier as default API
├── core.py # mix_entropy, bytes_to_float
├── proof.py # RandomProof, HeavyProof dataclasses
├── chains/ # blockchain entropy sources (eth, btc, sol)
├── standard/ # 3 exchanges + ETH/BTC/SOL + Argon2 (t=4, m=64MB)
└── heavy/ # inverse portfolio optimization → Standard pipeline
No stdlib random — no import random anywhere in the codebase. Every call re-runs the full entropy pipeline (no accumulated state or counter).
# Simplified (core.py / standard/engine.py)
mixed = sha512(coin_data + block_data + timestamp + os.urandom(32))
seed = argon2id(mixed, salt, t=4, m=64MB) # stretch
value = (int.from_bytes(seed[:8]) >> 11) / 2**53 # top 53 bits -> [0, 1)Manipulating Standard mode requires simultaneously moving multiple coins across Binance, Upbit, and Coinbase in the exact direction needed while also controlling ETH/BTC/SOL blocks — estimated cost: billions of dollars. Heavy additionally hides the target coins until optimization runs.
MIT