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['Bid'] 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 rate = (price['Ask'] - to_price) / to_price if rate < 0.01: rates.append(FX(price['MaterialTicker'], to_price, rate, price['AskCount'])) rates.sort() print('mat rate per shipping max converted') for rate in rates: mat = materials[rate.ticker] if mat['Weight'] >= mat['Volume']: if (per_t := rate.to_price / mat['Weight']) < 1000: continue per_shipping = f'{per_t:9,.0f}/t ' else: if (per_m3 := rate.to_price / mat['Volume']) < 1000: continue per_shipping = f'{per_m3:9,.0f}/m³' print(f'{rate.ticker:4} {rate.rate:8.5f} {per_shipping} {rate.depth * rate.to_price:12,.0f}') class RawPrice(typing.TypedDict): MaterialTicker: str ExchangeCode: str Ask: float | None Bid: float | None AskCount: int @dataclasses.dataclass(eq=False, frozen=True, slots=True) class FX: ticker: str to_price: float rate: float depth: int def __lt__(self, other: FX) -> bool: return self.rate < other.rate if __name__ == '__main__': main()