|
|
@@ -4,8 +4,11 @@ import dataclasses
|
|
|
import typing
|
|
|
|
|
|
import cache
|
|
|
+from config import config
|
|
|
|
|
|
def main() -> None:
|
|
|
+ check_cxos()
|
|
|
+
|
|
|
raw_prices: list[RawPrice] = cache.get('https://refined-prun.github.io/refined-prices/all.json')
|
|
|
markets: list[Market] = []
|
|
|
for price in raw_prices:
|
|
|
@@ -27,6 +30,32 @@ def main() -> None:
|
|
|
for market in markets:
|
|
|
print(f'{market.full_ticker:>8} {market.bid:5} {market.ask:5} {market.spread*100: 5.0f}% {market.traded:7}')
|
|
|
|
|
|
+def check_cxos() -> None:
|
|
|
+ orders: typing.Sequence[ExchangeOrder] = cache.get('https://rest.fnar.net/cxos/' + config.username,
|
|
|
+ headers={'Authorization': config.fio_api_key})
|
|
|
+ summary: typing.Mapping[tuple[str, str], ExchangeSummary] = {
|
|
|
+ (summary['MaterialTicker'], summary['ExchangeCode']): summary
|
|
|
+ for summary in cache.get('https://rest.fnar.net/exchange/all')
|
|
|
+ }
|
|
|
+ for order in orders:
|
|
|
+ state = summary[order['MaterialTicker'], order['ExchangeCode']]
|
|
|
+ if order['OrderType'] == 'BUYING' and state['Bid'] is not None and state['Bid'] > order['Limit']:
|
|
|
+ print('outbid on', f'{order["MaterialTicker"]}.{order["ExchangeCode"]}')
|
|
|
+ elif order['OrderType'] == 'SELLING' and state['Ask'] is not None and state['Ask'] < order['Limit']:
|
|
|
+ print('undercut on', f'{order["MaterialTicker"]}.{order["ExchangeCode"]}')
|
|
|
+
|
|
|
+class ExchangeOrder(typing.TypedDict):
|
|
|
+ MaterialTicker: str
|
|
|
+ ExchangeCode: str
|
|
|
+ OrderType: typing.Literal['SELLING'] | typing.Literal['BUYING']
|
|
|
+ Limit: float
|
|
|
+
|
|
|
+class ExchangeSummary(typing.TypedDict):
|
|
|
+ MaterialTicker: str
|
|
|
+ ExchangeCode: str
|
|
|
+ Bid: float | None
|
|
|
+ Ask: float | None
|
|
|
+
|
|
|
class RawPrice(typing.TypedDict):
|
|
|
FullTicker: str
|
|
|
Bid: float | None
|