#!/usr/bin/env python3 """Prices for materials across all exchanges, with VWAP and daily traded volume; optional fill price for a quantity. tools/price.py BHP STL # all CX tools/price.py BHP --cx AI1 --qty 200 # avg fill price to buy/sell 200 at AI1 (walks the live book) """ import argparse, sys from pathlib import Path sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) from puga import config, market def f(x, w=7): return f"{x:{w}.0f}" if x is not None else f"{'-':>{w}}" def main(): ap = argparse.ArgumentParser() ap.add_argument("tickers", nargs="+") ap.add_argument("--cx", help="limit to one exchange") ap.add_argument("--qty", type=float, help="show avg fill price for this quantity (needs --cx or uses default CX)") ap.add_argument("--refresh", action="store_true") a = ap.parse_args() snap = market.snapshot(a.refresh) print(f"{'mat':5} {'cx':4} {'bid':>7} {'ask':>7} {'vwap7':>7} {'vwap30':>7} {'trd/d7':>7} {'trd/d30':>7} {'demand':>7} {'supply':>7}") for t in map(str.upper, a.tickers): for cx in market.CXS: if a.cx and cx != a.cx: continue q = snap.get((t, cx)) if q: print(f"{t:5} {cx:4} {f(q.bid)} {f(q.ask)} {f(q.vwap7)} {f(q.vwap30)} {q.traded7:7.1f} {q.traded30:7.1f} {q.demand:7.0f} {q.supply:7.0f}") if a.qty: cx = a.cx or config.DEFAULT_CX b, s = market.walk(t, cx, a.qty, "buy"), market.walk(t, cx, a.qty, "sell") print(f" fill {a.qty:.0f} @ {cx}: buy avg {f(b['avg'])} (worst {f(b['worst'])}, filled {b['filled']:.0f}) | " f"sell avg {f(s['avg'])} (worst {f(s['worst'])}, filled {s['filled']:.0f})") if __name__ == "__main__": main()