Browse Source

market: split profit and fill time

raylu 2 weeks ago
parent
commit
4f053fe338
1 changed files with 19 additions and 13 deletions
  1. 19 13
      market.py

+ 19 - 13
market.py

@@ -2,6 +2,8 @@ from __future__ import annotations
 
 import collections
 import dataclasses
+import datetime
+import statistics
 import sys
 import typing
 
@@ -16,7 +18,7 @@ def main() -> None:
 		for ticker in exchange_tickers:
 			(price,) = (p for p in raw_prices if p['FullTicker'] == ticker)
 			a = analyze_price_chart(ticker, (price['Bid'] + price['Ask']) / 2) # pyright: ignore[reportOperatorIssue]
-			print(f'{ticker}: bids filled = {a.bids_filled:6.0f}, asks filled = {a.asks_filled:6.0f}, profit per interval = {a.profit_per_interval:10.1f}')
+			print(f'{ticker}: bids filled = {a.bids_filled:6.0f}, asks filled = {a.asks_filled:6.0f}, profit per interval = {a.profits:10.1f}')
 		return
 
 	check_cxos()
@@ -35,16 +37,15 @@ def main() -> None:
 		if spread < 0.15:
 			continue
 		chart_analysis = analyze_price_chart(price['FullTicker'], (price['Bid'] + price['Ask']) / 2)
-		max_profit = (price['Ask'] - price['Bid']) * min(chart_analysis.bids_filled, chart_analysis.asks_filled)
 		markets[price['ExchangeCode']].append(Market(price['FullTicker'], bid=price['Bid'], ask=price['Ask'],
-				spread=spread, max_profit=max_profit, chart_analysis=chart_analysis))
+				spread=spread, chart_analysis=chart_analysis))
 
-	print(' mat       bid   ask spread  bids filled  asks filled  profit/time  max profit')
+	print(' mat       bid   ask spread  bids filled  asks filled     profit  p75 fill time')
 	for commodities in markets.values():
 		commodities.sort(reverse=True)
 		for m in commodities:
 			print(f'{m.full_ticker:>8} {m.bid:5} {m.ask:5} {m.spread*100: 5.0f}% {m.chart_analysis.bids_filled:12.0f} '
-					f'{m.chart_analysis.asks_filled:12.0f} {m.chart_analysis.profit_per_interval:12.0f} {m.max_profit:11.0f}')
+					f'{m.chart_analysis.asks_filled:12.0f} {m.chart_analysis.profits:10.0f}  {m.chart_analysis.p75_fill_time}')
 		print()
 
 def check_cxos() -> None:
@@ -82,7 +83,8 @@ def analyze_price_chart(exchange_ticker: str, midpoint: float) -> ChartAnalysis:
 	pcpoints.reverse()
 	five_min = 5 * 60 * 1000
 	asks_filled: list[AskFilled] = []
-	r = ChartAnalysis(bids_filled=0, asks_filled=0, profit_per_interval=0)
+	fill_time = []
+	r = ChartAnalysis(bids_filled=0, asks_filled=0, profits=0, p75_fill_time=datetime.timedelta.max)
 	for hist in pcpoints:
 		time = hist['DateEpochMs'] // five_min
 		bids = asks = 0
@@ -103,24 +105,28 @@ def analyze_price_chart(exchange_ticker: str, midpoint: float) -> ChartAnalysis:
 			asks = int(interval_asks)
 		if bids and asks:
 			intra_interval_trades = min(bids, asks)
-			r.profit_per_interval += (hist['High'] - hist['Low'])	* intra_interval_trades
+			r.profits += (hist['High'] - hist['Low'])	* intra_interval_trades
 			bids -= intra_interval_trades
 			asks -= intra_interval_trades
 		assert bids == 0 or asks == 0
 		while bids > 0 and len(asks_filled) > 0:
-			profit_per_unit_per_interval = (asks_filled[-1].price - hist['Low']) / (asks_filled[-1].time - time)
+			profit = (asks_filled[-1].price - hist['Low'])
 			if asks_filled[-1].amount >= bids:
-				r.profit_per_interval += bids * profit_per_unit_per_interval
+				r.profits += bids * profit
 				asks_filled[-1].amount -= bids
 				if asks_filled[-1].amount == 0:
+					fill_time.append(asks_filled[-1].time - time)
 					asks_filled.pop()
 				bids = 0
 			else:
-				r.profit_per_interval += asks_filled[-1].amount * profit_per_unit_per_interval
+				r.profits += asks_filled[-1].amount * profit
 				bids -= asks_filled[-1].amount
+				fill_time.append(asks_filled[-1].time - time)
 				asks_filled.pop()
 		if asks:
 			asks_filled.append(AskFilled(price=hist['High'], amount=asks, time=time))
+	if len(fill_time) > 0:
+		r.p75_fill_time = statistics.quantiles(fill_time, n=4)[2] * datetime.timedelta(minutes=5)
 	return r
 
 class ExchangeOrder(typing.TypedDict):
@@ -180,7 +186,8 @@ class AskFilled:
 class ChartAnalysis:
 	bids_filled: float
 	asks_filled: float
-	profit_per_interval: float
+	profits: float
+	p75_fill_time: datetime.timedelta
 
 @dataclasses.dataclass(eq=False, frozen=True, slots=True)
 class Market:
@@ -188,11 +195,10 @@ class Market:
 	bid: float
 	ask: float
 	spread: float
-	max_profit: float
 	chart_analysis: ChartAnalysis
 
 	def __lt__(self, o: Market) -> bool:
-		return self.chart_analysis.profit_per_interval < o.chart_analysis.profit_per_interval
+		return self.chart_analysis.profits < o.chart_analysis.profits
 
 if __name__ == '__main__':
 	main()