mirror of
https://github.com/saymrwulf/BraiinsRatchet.git
synced 2026-05-14 20:37:52 +00:00
Add plain English report interpretation
This commit is contained in:
parent
5691bbb299
commit
057c0fca1e
4 changed files with 75 additions and 3 deletions
|
|
@ -64,7 +64,7 @@ Watcher-only tokens are only relevant if we later need account-specific read-onl
|
||||||
The Braiins market report distinguishes visible top-of-book from executable depth:
|
The Braiins market report distinguishes visible top-of-book from executable depth:
|
||||||
|
|
||||||
- `best_ask_btc_per_eh_day`: cheapest visible ask.
|
- `best_ask_btc_per_eh_day`: cheapest visible ask.
|
||||||
- `fillable_price_btc_per_eh_day`: cheapest ask level with enough unmatched supply for the configured target PH/s.
|
- `fillable_price_btc_per_eh_day`: cheapest ask level with enough unmatched supply for the configured canary-sized target PH/s.
|
||||||
- `suggested_bid_btc_per_eh_day`: fillable price plus the configured overpay cushion.
|
- `suggested_bid_btc_per_eh_day`: fillable price plus the configured overpay cushion.
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
|
||||||
|
|
@ -22,5 +22,5 @@ recommend_only = true
|
||||||
target_duration_minutes = 180
|
target_duration_minutes = 180
|
||||||
target_spend_btc = "0.00010"
|
target_spend_btc = "0.00010"
|
||||||
risk_lambda = "0.35"
|
risk_lambda = "0.35"
|
||||||
shadow_target_ph = "10"
|
shadow_target_ph = "2"
|
||||||
shadow_overpay_btc_per_eh_day = "0.01"
|
shadow_overpay_btc_per_eh_day = "0.01"
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,7 @@ The market is not a money-printer setup, but the expected loss is inside the con
|
||||||
Important fields:
|
Important fields:
|
||||||
|
|
||||||
- `best_ask_btc_per_eh_day`: current buy reference from Braiins.
|
- `best_ask_btc_per_eh_day`: current buy reference from Braiins.
|
||||||
- `fillable_price_btc_per_eh_day`: depth-aware price where enough unmatched ask supply exists for the configured target PH/s.
|
- `fillable_price_btc_per_eh_day`: depth-aware price where enough unmatched ask supply exists for the configured canary-sized target PH/s.
|
||||||
- `suggested_bid_btc_per_eh_day`: fillable price plus the configured overpay cushion; this is the shadow-autopilot would-bid price.
|
- `suggested_bid_btc_per_eh_day`: fillable price plus the configured overpay cushion; this is the shadow-autopilot would-bid price.
|
||||||
- `breakeven_btc_per_eh_day`: estimated mining EV at current OCEAN/network inputs.
|
- `breakeven_btc_per_eh_day`: estimated mining EV at current OCEAN/network inputs.
|
||||||
- `score_btc`: risk-adjusted expected value. Negative means no action.
|
- `score_btc`: risk-adjusted expected value. Negative means no action.
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,12 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from decimal import Decimal
|
||||||
|
|
||||||
from .models import MarketSnapshot, OceanSnapshot, PriceStats, StrategyProposal
|
from .models import MarketSnapshot, OceanSnapshot, PriceStats, StrategyProposal
|
||||||
from .storage import latest_market_snapshot, latest_ocean_snapshot, latest_proposal, market_price_stats
|
from .storage import latest_market_snapshot, latest_ocean_snapshot, latest_proposal, market_price_stats
|
||||||
|
|
||||||
|
SATOSHIS_PER_BTC = Decimal("100000000")
|
||||||
|
|
||||||
|
|
||||||
def build_text_report(conn, *, sample_limit: int = 50) -> str:
|
def build_text_report(conn, *, sample_limit: int = 50) -> str:
|
||||||
ocean = latest_ocean_snapshot(conn)
|
ocean = latest_ocean_snapshot(conn)
|
||||||
|
|
@ -16,6 +20,8 @@ def build_text_report(conn, *, sample_limit: int = 50) -> str:
|
||||||
lines.extend(_market_lines(market, stats))
|
lines.extend(_market_lines(market, stats))
|
||||||
lines.append("")
|
lines.append("")
|
||||||
lines.extend(_proposal_lines(proposal))
|
lines.extend(_proposal_lines(proposal))
|
||||||
|
lines.append("")
|
||||||
|
lines.extend(_plain_english_lines(ocean, market, proposal))
|
||||||
return "\n".join(lines)
|
return "\n".join(lines)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -73,6 +79,72 @@ def _proposal_lines(proposal: StrategyProposal | None) -> list[str]:
|
||||||
return lines
|
return lines
|
||||||
|
|
||||||
|
|
||||||
|
def _plain_english_lines(
|
||||||
|
ocean: OceanSnapshot | None,
|
||||||
|
market: MarketSnapshot | None,
|
||||||
|
proposal: StrategyProposal | None,
|
||||||
|
) -> list[str]:
|
||||||
|
lines = ["Plain English"]
|
||||||
|
if ocean is None or market is None or proposal is None:
|
||||||
|
return lines + [" Not enough data yet. Run ./scripts/ratchet once."]
|
||||||
|
|
||||||
|
lines.append(f" Decision: {_decision_sentence(proposal)}")
|
||||||
|
|
||||||
|
if market.best_ask_btc_per_eh_day is not None and market.fillable_price_btc_per_eh_day is not None:
|
||||||
|
gap = market.fillable_price_btc_per_eh_day - market.best_ask_btc_per_eh_day
|
||||||
|
lines.append(
|
||||||
|
" Market depth: the visible best ask is "
|
||||||
|
f"{market.best_ask_btc_per_eh_day}, but enough depth for "
|
||||||
|
f"{_fmt(market.fillable_target_ph)} PH/s starts at {market.fillable_price_btc_per_eh_day} "
|
||||||
|
f"(gap {gap})."
|
||||||
|
)
|
||||||
|
elif market.best_ask_btc_per_eh_day is not None:
|
||||||
|
lines.append(
|
||||||
|
" Market depth: only the visible best ask was available; fillable depth was not computed."
|
||||||
|
)
|
||||||
|
|
||||||
|
if proposal.breakeven_btc_per_eh_day is not None and proposal.order is not None:
|
||||||
|
edge = proposal.breakeven_btc_per_eh_day - proposal.order.price_btc_per_eh_day
|
||||||
|
lines.append(
|
||||||
|
" Price check: proposed price is "
|
||||||
|
f"{proposal.order.price_btc_per_eh_day}; estimated breakeven is "
|
||||||
|
f"{proposal.breakeven_btc_per_eh_day}; edge is {edge} BTC/EH/day."
|
||||||
|
)
|
||||||
|
|
||||||
|
if proposal.order is not None:
|
||||||
|
lines.append(
|
||||||
|
" Manual canary card: spend "
|
||||||
|
f"{proposal.order.spend_btc} BTC (~{_btc_to_sats(proposal.order.spend_btc)} sats), "
|
||||||
|
f"duration {proposal.order.duration_minutes} minutes, estimated speed "
|
||||||
|
f"{proposal.order.implied_hashrate_eh_s * Decimal('1000')} PH/s."
|
||||||
|
)
|
||||||
|
|
||||||
|
lines.append(
|
||||||
|
" Expected result: "
|
||||||
|
f"{proposal.expected_net_btc} BTC (~{_btc_to_sats(proposal.expected_net_btc)} sats) before luck; "
|
||||||
|
"this is a model estimate, not a promise."
|
||||||
|
)
|
||||||
|
lines.append(f" Wait time: {proposal.maturity_note}.")
|
||||||
|
lines.append(
|
||||||
|
" Rule: manual_canary means buying information with bounded downside; "
|
||||||
|
"manual_bid means the stricter profit-seeking guardrails cleared."
|
||||||
|
)
|
||||||
|
return lines
|
||||||
|
|
||||||
|
|
||||||
|
def _decision_sentence(proposal: StrategyProposal) -> str:
|
||||||
|
if proposal.action == "observe":
|
||||||
|
return "do nothing."
|
||||||
|
if proposal.action == "manual_canary":
|
||||||
|
return "a tiny manual research canary is allowed by the loss budget, but this is not a profit signal."
|
||||||
|
return "a manual profit-seeking bid cleared the stricter guardrails."
|
||||||
|
|
||||||
|
|
||||||
|
def _btc_to_sats(value: Decimal) -> str:
|
||||||
|
sats = value * SATOSHIS_PER_BTC
|
||||||
|
return str(sats.quantize(Decimal("1")))
|
||||||
|
|
||||||
|
|
||||||
def _fmt(value: object) -> str:
|
def _fmt(value: object) -> str:
|
||||||
if value is None:
|
if value is None:
|
||||||
return "n/a"
|
return "n/a"
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue