from __future__ import annotations import dataclasses import sys import typing import cache import roi def main() -> None: from_cx, to_cx = sys.argv[1:] raw_prices: list[RawPrice] = cache.get('https://refined-prun.github.io/refined-prices/all.json') materials: dict[str, roi.Material] = {m['Ticker']: m for m in cache.get('https://api.prunplanner.org/data/materials')} bids: dict[str, float] = {} for price in raw_prices: if price['ExchangeCode'] != to_cx or price['MMBuy'] is None: continue assert price['Bid'] is not None bids[price['MaterialTicker']] = price['Bid'] rates: list[FX] = [] for price in raw_prices: if price['ExchangeCode'] != from_cx or price['Ask'] is None or (to_price := bids.get(price['MaterialTicker'])) is None: continue rates.append(FX(price['MaterialTicker'], to_price, (price['Ask'] - to_price) / to_price)) rates.sort() for rate in rates: print(f'{rate.ticker:4} {rate.rate:8.5f}', end=' ') mat = materials[rate.ticker] if mat['Weight'] >= mat['Volume']: print(f'{rate.to_price / mat["Weight"]:9,.0f}/t') else: print(f'{rate.to_price / mat["Volume"]:9,.0f}/m³') class RawPrice(typing.TypedDict): MaterialTicker: str ExchangeCode: str Ask: float | None Bid: float | None MMBuy: float | None @dataclasses.dataclass(eq=False, frozen=True, slots=True) class FX: ticker: str to_price: float rate: float def __lt__(self, other: FX) -> bool: return self.rate < other.rate if __name__ == '__main__': main()