market_stats.py 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. from __future__ import annotations
  2. import collections
  3. import datetime
  4. import json
  5. import typing
  6. import dulwich.repo
  7. import dulwich.objects
  8. if typing.TYPE_CHECKING:
  9. import market
  10. def main() -> None:
  11. repo = dulwich.repo.Repo('../refined-prices')
  12. today = datetime.datetime.now(tz=datetime.UTC).replace(hour=0, minute=0, second=0, microsecond=0)
  13. sunday = (today - datetime.timedelta(days=(today.weekday() + 1) % 7))
  14. for _ in range(52):
  15. analyze_markets(prices_on_day(repo, sunday))
  16. sunday -= datetime.timedelta(days=7)
  17. def prices_on_day(repo: dulwich.repo.Repo, day: datetime.datetime) -> typing.Sequence[market.RawPrice]:
  18. '''refined-prices for the earliest commit on the given day'''
  19. day_ts = int(day.timestamp())
  20. next_day_ts = int((day + datetime.timedelta(days=1)).timestamp())
  21. *_, entry = repo.get_walker(paths=[b'all.json'], since=day_ts, until=next_day_ts)
  22. dt = datetime.datetime.fromtimestamp(entry.commit.author_time, tz=datetime.UTC)
  23. print('loading refined-prices', dt, entry.commit.tree.decode())
  24. tree = typing.cast(dulwich.objects.Tree, repo[entry.commit.tree])
  25. _, blob = tree[b'all.json']
  26. return json.loads(typing.cast(dulwich.objects.Blob, repo[blob]).data.decode())
  27. def analyze_markets(prices: typing.Sequence[market.RawPrice]) -> None:
  28. markets: dict[str, list[market.RawPrice]] = collections.defaultdict(list)
  29. for price in prices:
  30. if price['ExchangeCode'].endswith('2'):
  31. continue
  32. markets[price['MaterialTicker']].append(price)
  33. markets_with_trades = ranking = ic1_lowest = gap = 0
  34. for mat, mat_prices in markets.items():
  35. mat_prices.sort(key=lambda p: (p['Traded7D'] or 0))
  36. if mat_prices[0]['Traded7D'] == None:
  37. continue
  38. markets_with_trades += 1
  39. for index, price in enumerate(mat_prices):
  40. if price['ExchangeCode'] == 'IC1':
  41. break
  42. else:
  43. raise AssertionError('IC1 not found for ' + mat)
  44. ranking += index
  45. if index == 0:
  46. ic1_lowest += 1
  47. gap += (mat_prices[1]['Traded7D'] - mat_prices[0]['Traded7D']) / mat_prices[1]['Traded7D'] # type: ignore
  48. print(f'IC1 ranking {ranking}, lowest in {ic1_lowest} of {markets_with_trades} markets, gap {gap:.2f}')
  49. if __name__ == '__main__':
  50. main()