buy.py 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. from __future__ import annotations
  2. import collections
  3. import dataclasses
  4. import typing
  5. import cache
  6. from config import config
  7. import supply
  8. if typing.TYPE_CHECKING:
  9. import market
  10. def main() -> None:
  11. raw_prices: typing.Mapping[str, market.RawPrice] = {p['MaterialTicker']: p
  12. for p in cache.get('https://refined-prun.github.io/refined-prices/all.json') if p['ExchangeCode'] == 'IC1'}
  13. # what we need to buy
  14. planets = [supply.Planet(fio_burn) for fio_burn in cache.get('https://rest.fnar.net/fioweb/burn/user/' + config.username,
  15. headers={'Authorization': config.fio_api_key})]
  16. buy: dict[str, int] = collections.defaultdict(int)
  17. for planet in planets:
  18. for mat, amount in planet.buy_for_target(7).items():
  19. buy[mat] += amount
  20. # what we have
  21. warehouses: typing.Sequence[market.Warehouse] = cache.get('https://rest.fnar.net/sites/warehouses/' + config.username,
  22. headers={'Authorization': config.fio_api_key})
  23. for warehouse in warehouses:
  24. if warehouse['LocationNaturalId'] == 'HRT':
  25. storage: market.Storage = cache.get(f'https://rest.fnar.net/storage/{config.username}/{warehouse["StoreId"]}',
  26. headers={'Authorization': config.fio_api_key})
  27. assert storage['Type'] == 'WAREHOUSE_STORE'
  28. warehouse = {item['MaterialTicker']: item['MaterialAmount'] for item in storage['StorageItems']}
  29. break
  30. else:
  31. raise Exception("couldn't find HRT warehouse")
  32. # what we already are bidding for
  33. orders: typing.Sequence[market.ExchangeOrder] = cache.get('https://rest.fnar.net/cxos/' + config.username,
  34. headers={'Authorization': config.fio_api_key})
  35. orders = [order for order in orders
  36. if order['OrderType'] == 'BUYING' and order['Status'] != 'FILLED' and order['ExchangeCode'] == 'IC1']
  37. bids = collections.defaultdict(int)
  38. for order in orders:
  39. bids[order['MaterialTicker']] += order['Amount']
  40. # what's left to buy
  41. materials: list[Material] = []
  42. for mat, amount in buy.items():
  43. remaining = amount - bids[mat] - warehouse.get(mat, 0)
  44. if remaining <= 0:
  45. continue
  46. price = raw_prices[mat]
  47. if price['Bid'] is None or price['Ask'] is None:
  48. print(mat, 'has no bid/ask')
  49. continue
  50. spread = price['Ask'] - price['Bid']
  51. materials.append(Material(mat, amount=amount, bids=bids[mat], warehouse=warehouse.get(mat, 0),
  52. spread=spread, savings=spread * remaining))
  53. materials.sort(reverse=True)
  54. print('mat want bids have buy savings')
  55. for m in materials:
  56. print(f'{m.ticker:4} {m.amount:>5} {m.bids:>5} {m.warehouse:>5} {m.amount - m.bids - m.warehouse:>5} {m.savings:8.0f}')
  57. # deposits of current bids
  58. orders.sort(key=lambda order: order['Limit'] * order['Amount'], reverse=True)
  59. print('\ncurrent bid deposits:')
  60. for order in orders:
  61. print(f"{order['MaterialTicker']:4} {order['Limit'] * order['Amount']:7,.0f}")
  62. @dataclasses.dataclass(eq=False, slots=True)
  63. class Material:
  64. ticker: str
  65. amount: int
  66. bids: int
  67. warehouse: int
  68. spread: float
  69. savings: float
  70. def __lt__(self, o: Material) -> bool:
  71. return self.savings< o.savings
  72. if __name__ == '__main__':
  73. main()