Kaynağa Gözat

movers: find thin supply

raylu 1 hafta önce
ebeveyn
işleme
622829999b
1 değiştirilmiş dosya ile 32 ekleme ve 0 silme
  1. 32 0
      movers.py

+ 32 - 0
movers.py

@@ -15,6 +15,7 @@ def main() -> None:
 
 	movers: dict[str, list[Mover]] = collections.defaultdict(list)
 	shortages: dict[str, list[Mover]] = collections.defaultdict(list)
+	traded_map: dict[str, int] = {}
 	for current_price in current_prices:
 		if current_price['ExchangeCode'].endswith('2'):
 			continue
@@ -25,6 +26,9 @@ def main() -> None:
 			if mover.days_supply_lost > 7 and mover.days_supply_remaining < 14:
 				shortages[mover.ticker].append(mover)
 
+			assert (traded := current_price['AverageTraded30D']) is not None
+			traded_map[current_price['FullTicker']] = int(traded)
+
 	for ticker_movers in movers.values():
 		ticker_movers.sort(reverse=True)
 	for ticker_shortages in shortages.values():
@@ -41,6 +45,30 @@ def main() -> None:
 		print(f'{-commodity[0].days_supply_lost:6.1f}d', f'{commodity[0].supply_consumption_rate:7.1f}/d',
 				' '.join(f'{mover.ticker}.{mover.exchange_code}' for mover in commodity))
 
+	print('\nthin supply:')
+	for ticker, ticker_shortages in shortages.items():
+		for commodity in ticker_shortages:
+			exchange_ticker = f'{commodity.ticker}.{commodity.exchange_code}'
+			asks: list[Order] = cache.get(f'https://rest.fnar.net/exchange/{exchange_ticker}')['SellingOrders']
+			if len(asks) == 0:
+				print(f'{exchange_ticker:3}: no asks')
+				continue
+			asks.sort(key=lambda o: o['ItemCost'], reverse=True)
+			current_ask = asks[-1]['ItemCost']
+			traded = traded_map[exchange_ticker]
+			remaining = traded // 2
+			expected_price = float('-infinity')
+			while remaining > 0:
+				if len(asks) == 0:
+					expected_price = float('infinity')
+					break
+				if asks[-1]['ItemCount'] > remaining:
+					expected_price = asks[-1]['ItemCost']
+					break
+				remaining -= asks.pop()['ItemCount']
+			if (expected_price - current_ask) / current_ask > 0.15:
+				print(f'{exchange_ticker:>7}: {traded:7,} {current_ask:10,.2f} → {expected_price:10,.2f}')
+
 def get_old_prices() -> typing.Mapping[str, RawPrice]:
 	week_ago = datetime.datetime.now(datetime.UTC) - datetime.timedelta(days=OLD_PRICE_DAYS)
 	commits = cache.get(f'https://api.github.com/repos/refined-prun/refined-prices/commits?until={week_ago.isoformat()}&per_page=1')
@@ -68,6 +96,10 @@ class RawPrice(typing.TypedDict):
 	AverageTraded30D: float | None # averaged daily traded volume over last 30 days
 	Supply: int
 
+class Order(typing.TypedDict):
+	ItemCount: int
+	ItemCost: float
+
 @dataclasses.dataclass(eq=False, frozen=True, slots=True)
 class Mover:
 	exchange_code: str