Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Buy or Wait?

A deterministic, evidence-aware affordability engine that answers "Can I afford this?": when to pay, how much, and on what plan.

Python Dependencies Deterministic License

Built for the HackerRank Orchestrate 24-hour hackathon (September 2026).

For each purchase request, the engine rebuilds the user's real cash position from messy transaction history. It reads amounts from receipt images and interprets multilingual messages, then forecasts 90 days ahead. From that forecast it picks the safest plan the user will accept: pay in full, pay partially, use installments, wait, or don't proceed.

$ python3 code/main.py
wrote output.csv (250 rows)          # ~0.5s, zero model calls, zero dependencies

Highlights

  • Deterministic core, AI at the edges. Six of the seven output columns are arithmetic or enum choices with one correct answer, so the core is a cash-flow simulator, not an LLM guessing numbers. AI only reads receipt images and interprets free text. It outputs typed data, and the simulator uses that data.
  • One quantity answers everything. A payment on day D shifts the whole forecast curve down from D onward. The largest safe payment today is therefore the headroom at the curve's trough: amount_safe_to_pay = clamp(trough_90d − minimum_balance, 0, requested_amount).
  • Resolves hidden traps in the data. It handles cancelled authorisations, failed debits with retries, duplicate pending charges, unsettled refunds, non-cash portfolio valuations, blank amounts that must be read from images, and foreign-currency events converted at the rate for their date.
  • Injection-resistant by construction. The message corpus includes a real advance-fee scam in two languages. Message text never reaches a prompt that can act. Only a fixed set of 16 typed operations can change a forecast, so the instruction "pay the release fee" can't be expressed at all. The self-test checks this against corpus messages and adversarial probes.
  • Measured, not tuned. A 75-day horizon scored higher on the labelled samples. I rejected it because it contradicts the spec and hides an unexplained bias. Every tempting shortcut that scored worse is recorded in lab/FINDINGS.md.

Results

Local scorer against the 25 published labelled examples:

Column Accuracy
affordability_status 80.0%
recommended_payment_method 84.0%
payment_plan 88.0%
earliest_date_for_full_payment 76.0%
spending_changes_needed 84.0%
amount_safe_to_pay 12/25 within 5%
Weighted overall 71.6 / 100

Reference points: the naive baseline ("always affordable, pay in full today") scores 25.7, and the ground truth scored against itself gives exactly 100.0. The full 250-request output passes all ~30 output checks with 0 errors, and the self-test passes 17/17.

Total AI cost for the whole dataset: $1.28, all spent once on extracting evidence. The production run makes 0 model calls (see usage_report.md).


Quick start

No installation and no dependencies. Needs Python 3.8+.

git clone https://github.com/Safeer1877/buy-or-wait.git
cd buy-or-wait

# predict all 250 requests -> output.csv
python3 code/main.py

# score against the 25 labelled examples
python3 code/main.py --requests dataset/sample_requests.csv --out /tmp/samples.csv
python3 code/evaluation/score.py --pred /tmp/samples.csv --truth dataset/sample_requests.csv

# check the output format and business rules
python3 code/evaluation/validate.py --pred output.csv --dataset dataset

# test the evidence layer, including the prompt-injection defence
python3 code/evaluation/selftest.py

Add --verbose to print the evidence applied to each request. --refresh-evidence re-extracts receipt amounts with a vision model and needs ANTHROPIC_API_KEY. Without a key, the engine uses the audited cache.

How it works

 financial_events ─┐
 profiles ─────────┤                       ┌──────────────┐     ┌────────────┐     ┌─────────┐
 exchange_rates ───┼─► reconstruct ───────►│  90-day      │────►│  planner   │────►│ explain │──► output.csv
 payment_options ──┘   (trap resolution,   │  forecast    │     │ (candidates│     └─────────┘
                        recurring streams) │  + trough    │     │  + ranking)│
 messages ─┐                ▲              └──────────────┘     └────────────┘
 images ───┴─► evidence ────┘
              (typed, whitelisted operations)
Module Responsibility
bow/loader.py Dataset joins and dated FX conversion (fails loudly instead of converting at the wrong rate)
bow/evidence.py Turns images and messages into typed, whitelisted operations
bow/reconstruct.py Trap resolution, recurring-stream detection, applying evidence
bow/forecast.py 90-day projection, trough, earliest safe date
bow/planner.py Candidate plans, safety checks, spending-change search, ranking
bow/explain.py Short explanations backed by the underlying figures

The full technical write-up is in code/README.md. It covers each stage, design decisions and the configuration flags that let every choice be re-measured.

Repository layout

code/                 the solution
  main.py             entry point
  bow/                engine modules
  evaluation/         scorer, output validator, self-test, token-usage report
  prompts/            image-extraction prompt and message-operation spec
  cache/              audited amounts extracted from receipt images, with provenance
lab/                  research record: findings, decisions, experiment harness, run history
dataset/              challenge input data (provided by HackerRank)
problem_statement.md  full challenge specification (provided by HackerRank)
output.csv            predictions for all 250 requests

Engineering process

I built the scoring harness and output validator before any solution code, so every change was measured rather than guessed. The lab/ directory keeps that record:

  • lab/FINDINGS.md: rules reverse-engineered from the labelled data, each backed by sample evidence
  • lab/DECISIONS.md: each design decision, with its reasoning and the alternatives I rejected
  • lab/runs/INDEX.md: the history of experiment scores

Acknowledgements

The problem statement and dataset are from the HackerRank Orchestrate September 2026 hackathon and belong to HackerRank. They are included here only so the solution can be run and reproduced. The MIT license covers the solution code in code/ and lab/.

About

Deterministic, evidence-aware affordability engine: 90-day cash-flow forecasting, receipt OCR and injection-resistant message parsing to decide buy, wait, or pay in installments. HackerRank Orchestrate 2026.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages