|
|
@@ -1,65 +1,60 @@
|
|
|
from __future__ import annotations
|
|
|
|
|
|
import collections
|
|
|
-import dataclasses
|
|
|
+import math
|
|
|
+import sys
|
|
|
import typing
|
|
|
|
|
|
import cache
|
|
|
from config import config
|
|
|
import market
|
|
|
+import supply
|
|
|
|
|
|
if typing.TYPE_CHECKING:
|
|
|
import supply
|
|
|
|
|
|
def main() -> None:
|
|
|
+ (ship,) = sys.argv[1:]
|
|
|
+ ship_inventory = get_ship_storage(ship)
|
|
|
+ warehouse_inventory = supply.warehouse_inventory()
|
|
|
raw_prices: typing.Mapping[str, market.RawPrice] = {p['MaterialTicker']: p
|
|
|
for p in cache.get('https://refined-prun.github.io/refined-prices/all.json') if p['ExchangeCode'] == 'IC1'}
|
|
|
-
|
|
|
- planets: typing.Sequence[supply.FIOBurn] = cache.get('https://rest.fnar.net/fioweb/burn/user/' + config.username,
|
|
|
- headers={'Authorization': config.fio_api_key})
|
|
|
- producing = frozenset(mat['MaterialTicker'] for planet in planets for mat in planet['OrderProduction']
|
|
|
- if mat['MaterialTicker'] not in (c['MaterialTicker'] for c in planet['OrderConsumption']))
|
|
|
- materials: list[Material] = []
|
|
|
- for mat in producing:
|
|
|
- price = raw_prices[mat]
|
|
|
- if price['Bid'] is None or price['Ask'] is None:
|
|
|
- print(mat, 'has no bid/ask')
|
|
|
- continue
|
|
|
- spread = (price['Ask'] - price['Bid']) / price['Ask']
|
|
|
- chart_analysis = market.analyze_price_chart(mat + '.IC1', (price['Bid'] + price['Ask']) / 2)
|
|
|
- ask_fill_ratio = chart_analysis.asks_filled / (chart_analysis.bids_filled + chart_analysis.asks_filled)
|
|
|
- materials.append(Material(mat, spread=spread, bid=price['Bid'], ask=price['Ask'], score=spread * ask_fill_ratio))
|
|
|
- materials.sort()
|
|
|
-
|
|
|
- all_orders: typing.Sequence[market.ExchangeOrder] = cache.get('https://rest.fnar.net/cxos/' + config.username,
|
|
|
+ consumption = get_consumption()
|
|
|
+
|
|
|
+ for item in ship_inventory:
|
|
|
+ ticker = item['MaterialTicker']
|
|
|
+ print(f'{item["MaterialAmount"]:5} {ticker:3}:', end=' ')
|
|
|
+ have = item['MaterialAmount'] + warehouse_inventory.get(ticker, 0)
|
|
|
+ need = math.ceil(consumption.get(ticker, 0) * 14)
|
|
|
+ sell = min(have - need, item['MaterialAmount'])
|
|
|
+ keep = item['MaterialAmount'] - sell
|
|
|
+ if sell > 0:
|
|
|
+ print('sell', sell, end=' ')
|
|
|
+ if keep > 0:
|
|
|
+ print('keep', keep, end= ' ')
|
|
|
+ print()
|
|
|
+
|
|
|
+def get_ship_storage(ship_name: str) -> typing.Sequence[market.StorageItem]:
|
|
|
+ ship_name = ship_name.casefold()
|
|
|
+ stores: typing.Sequence[market.Storage] = cache.get('https://rest.fnar.net/storage/' + config.username,
|
|
|
headers={'Authorization': config.fio_api_key})
|
|
|
- orders: dict[str, int] = collections.defaultdict(int)
|
|
|
- for order in all_orders:
|
|
|
- if order['OrderType'] != 'SELLING' or order['Status'] == 'FILLED' or order['ExchangeCode'] != 'IC1':
|
|
|
- continue
|
|
|
- orders[order['MaterialTicker']] += order['Amount']
|
|
|
-
|
|
|
- print(f'{"mat":^4} spread asks instant cash loss')
|
|
|
- for m in materials:
|
|
|
- print(f'{m.ticker:4} {m.spread*100:5.1f}%', end='')
|
|
|
- if asks := orders.pop(m.ticker, None):
|
|
|
- print(f' {asks:5} {asks * m.bid:13} {asks * (m.ask - m.bid):5}')
|
|
|
- else:
|
|
|
- print()
|
|
|
- print('\nother listings:')
|
|
|
- for mat, asks in orders.items():
|
|
|
- print(f'{mat:4} {asks:5}')
|
|
|
-
|
|
|
-@dataclasses.dataclass(eq=False, slots=True)
|
|
|
-class Material:
|
|
|
- ticker: str
|
|
|
- spread: float
|
|
|
- bid: float
|
|
|
- ask: float
|
|
|
- score: float
|
|
|
-
|
|
|
- def __lt__(self, o) -> bool:
|
|
|
- return self.score < o.score
|
|
|
+ for store in stores:
|
|
|
+ if store['Type'] == 'SHIP_STORE' and store['Name'].casefold() == ship_name:
|
|
|
+ return store['StorageItems']
|
|
|
+ raise Exception(f'ship storage {ship_name} not found')
|
|
|
+
|
|
|
+def get_consumption() -> typing.Mapping[str, float]:
|
|
|
+ '''get consumption on planets that consume each mat'''
|
|
|
+ planets = [supply.Planet(fio_burn) for fio_burn in cache.get('https://rest.fnar.net/fioweb/burn/user/' + config.username,
|
|
|
+ headers={'Authorization': config.fio_api_key})]
|
|
|
+
|
|
|
+ consumption: dict[str, float] = collections.defaultdict(float)
|
|
|
+ for planet in planets:
|
|
|
+ supply_config = config.supply_config(planet.name)
|
|
|
+ for mat, amount in planet.net_consumption.items():
|
|
|
+ if mat not in supply_config.ignore_materials and amount > 0:
|
|
|
+ consumption[mat] += amount
|
|
|
+ return consumption
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|