Răsfoiți Sursa

market_stats: handle ties

raylu 1 săptămână în urmă
părinte
comite
d028916be7
1 a modificat fișierele cu 23 adăugiri și 12 ștergeri
  1. 23 12
      market_stats.py

+ 23 - 12
market_stats.py

@@ -52,30 +52,41 @@ def analyze_markets(prices: typing.Sequence[market.RawPrice], date: datetime.dat
 			continue
 		markets[price['MaterialTicker']].append(price)
 
-	markets_with_trades = ranking = ic1_lowest = ic1_zero = gap = 0
+	markets_with_trades = total_rank = ic1_lowest = ic1_zero = gap = 0
 	for mat, mat_prices in markets.items():
-		mat_prices.sort(key=lambda p: (p['Traded7D'] or 0))
-		if mat_prices[-1]['Traded7D'] == None:
+		# find IC1's Traded7D rank among the CXes
+		# group CXes by Traded7D first in case of ties
+		rankings: dict[int, list[str]] = collections.defaultdict(list)
+		for price in mat_prices:
+			rankings[price['Traded7D'] or 0].append(price['ExchangeCode'])
+		if len(rankings) == 1 and 0 in rankings: # no markets had any trades
 			continue
-		markets_with_trades += 1
-		for index, price in enumerate(mat_prices):
-			if price['ExchangeCode'] == 'IC1':
+		sorted_markets = sorted(rankings.items(), key=lambda item: item[0])
+		rank = 0
+		for _, cxes in sorted_markets:
+			if 'IC1' in cxes:
 				break
+			rank += len(cxes)
 		else:
 			raise AssertionError('IC1 not found for ' + mat)
-		ranking += index
-		if index == 0:
+		markets_with_trades += 1
+		total_rank += rank
+
+		if rank == 0:
 			ic1_lowest += 1
-			ic1_traded = mat_prices[0]['Traded7D'] or 0
-			lowest_traded = mat_prices[1]['Traded7D'] or 0
+			ic1_traded = sorted_markets[0][0]
+			if len(sorted_markets[0][1]) > 1: # another market is tied for last with us
+				lowest_traded = ic1_traded
+			else:
+				lowest_traded = sorted_markets[1][0]
 			if lowest_traded > 0:
 				if ic1_traded == 0:
 					ic1_zero += 1
 				gap += (lowest_traded - ic1_traded) / lowest_traded
-	print(f'{markets_with_trades} markets with trades, IC1 ranking {ranking}, lowest in {ic1_lowest}, zero in {ic1_zero}, gap {gap:.2f}')
+	print(f'{markets_with_trades} markets with trades, IC1 total rank {total_rank}, lowest in {ic1_lowest}, zero in {ic1_zero}, gap {gap:.2f}')
 	return {
 		'date': date.isoformat(),
-		'ranking': ranking / markets_with_trades,
+		'ranking': total_rank / markets_with_trades,
 		'ic1_lowest': ic1_lowest / markets_with_trades * 100,
 		'ic1_zero': ic1_zero,
 		'gap': gap / markets_with_trades * 100,