|
1 | 1 | # This script is used to provide backend functionality for /src/page/delist_recommender.py
|
2 |
| -# It should make use of the backend state and middleware to fetch the data borrowing similar logic from /backend/api/asset_liability.py and /backend/api/health.py and /backend/api/price_shock.py |
3 | 2 |
|
4 |
| -# It should return a JSON object with the following fields: |
5 |
| -# - status: "success" or "error" |
6 |
| -# - message: a message to be displayed to the user |
7 |
| -# - data: a JSON object containing the data to be displayed to the user |
8 |
| - |
9 |
| -# This script provides backend functionality for delist recommender analysis |
10 |
| -# It makes use of the backend state and middleware to fetch data efficiently |
11 | 3 | import os
|
12 | 4 | import math
|
13 | 5 | import sys
|
|
43 | 35 | DAYS_TO_CONSIDER = 30
|
44 | 36 |
|
45 | 37 | # Drift API configuration
|
46 |
| -DRIFT_API_BASE_URL = "https://y7n4m4tnpb.execute-api.eu-west-1.amazonaws.com" |
47 |
| -DRIFT_API_HEADERS = {"X-Origin-Verify": "AolCE35uXby9TJHHgoz6"} |
| 38 | +DRIFT_DATA_API_BASE_URL = "https://y7n4m4tnpb.execute-api.eu-west-1.amazonaws.com" |
| 39 | +DRIFT_DATA_API_HEADERS = {"X-Origin-Verify": "AolCE35uXby9TJHHgoz6"} |
48 | 40 | API_RATE_LIMIT_INTERVAL = 0.1 # seconds between requests
|
49 | 41 |
|
| 42 | +# Drift Score Boost - These are symbols that get a score boost in the delist recommender |
| 43 | +DRIFT_SCORE_BOOST_SYMBOLS = { |
| 44 | + "DRIFT-PERP", |
| 45 | +} |
| 46 | + |
| 47 | +# Drift Score Boost Amount - The amount of score boost to apply to the symbols in DRIFT_SCORE_BOOST_SYMBOLS |
| 48 | +DRIFT_SCORE_BOOST_AMOUNT = 10 |
| 49 | + |
50 | 50 | # Global rate limiter variables for API calls
|
51 | 51 | rate_limit_lock = asyncio.Lock()
|
52 | 52 | last_request_time = 0.0
|
53 | 53 |
|
54 |
| -# Symbols to ignore completely during analysis |
| 54 | +# Prediction Market Symbols to ignore completely during analysis |
55 | 55 | IGNORED_SYMBOLS = {
|
56 | 56 | "TRUMP-WIN-2024-BET",
|
57 | 57 | "KAMALA-POPULAR-VOTE-2024-BET",
|
|
74 | 74 | # Note: Inputs to scoring ('MC', 'Spot Volume', etc.) are expected in full dollar amounts, not millions.
|
75 | 75 | DRIFT_SCORE_CUTOFFS = {
|
76 | 76 | 'Market Cap Score': {
|
77 |
| - 'MC': {'kind': 'exp', 'start': 1000000, 'end': 5000000000, 'steps': 20}, # $1M to $5B |
| 77 | + 'MC': {'kind': 'exp', 'start': 1_000_000, 'end': 5_000_000_000, 'steps': 20}, # $1M to $5B |
78 | 78 | },
|
79 | 79 | 'Spot Vol Score': {
|
80 | 80 | # Expects 'Spot Volume' (sum of avg daily vol) and 'Spot Vol Geomean' (geomean of top 3 avg daily vol) in full dollars
|
81 |
| - 'Spot Volume': {'kind': 'exp', 'start': 10000, 'end': 1000000000, 'steps': 10}, # $10k to $1B |
82 |
| - 'Spot Vol Geomean': {'kind': 'exp', 'start': 10000, 'end': 1000000000, 'steps': 10}, # $10k to $1B |
| 81 | + 'Spot Volume': {'kind': 'exp', 'start': 10_000, 'end': 1_000_000_000, 'steps': 10}, # $10k to $1B |
| 82 | + 'Spot Vol Geomean': {'kind': 'exp', 'start': 10_000, 'end': 1_000_000_000, 'steps': 10}, # $10k to $1B |
83 | 83 | },
|
84 | 84 | 'Futures Vol Score': {
|
85 | 85 | # Expects 'Fut Volume' (sum of avg daily vol) and 'Fut Vol Geomean' (geomean of top 3 avg daily vol) in full dollars
|
|
88 | 88 | },
|
89 | 89 | 'Drift Activity Score': {
|
90 | 90 | # Expects 'Volume on Drift' (estimated 30d vol) and 'OI on Drift' in full dollars
|
91 |
| - 'Volume on Drift': {'kind': 'exp', 'start': 1000, 'end': 500000000, 'steps': 10}, # $1k to $500M |
92 |
| - 'OI on Drift': {'kind': 'exp', 'start': 1000, 'end': 500000000, 'steps': 10}, # $1k to $500M |
| 91 | + 'Volume on Drift': {'kind': 'exp', 'start': 1_000, 'end': 500_000_000, 'steps': 10}, # $1k to $500M |
| 92 | + 'OI on Drift': {'kind': 'exp', 'start': 1_000, 'end': 500_000_000, 'steps': 10}, # $1k to $500M |
93 | 93 | },
|
94 | 94 | }
|
95 | 95 |
|
96 | 96 | # Score boundaries for delist recommendations
|
97 |
| -SCORE_LB = {0: 0, 5: 37, 10: 48, 20: 60} # Lower bounds |
| 97 | +SCORE_UB = {0: 62, 3: 75, 5: 85, 10: 101} # Upper Bound: If score >= this, consider increasing leverage |
| 98 | +SCORE_LB = {0: 0, 5: 37, 10: 48, 20: 60} # Lower Bound: If score < this, consider decreasing leverage/delisting |
98 | 99 |
|
99 | 100 | # Reference exchanges for market data
|
100 | 101 | REFERENCE_SPOT_EXCH = {
|
@@ -1327,6 +1328,15 @@ def build_scores(df):
|
1327 | 1328 | score_components = list(DRIFT_SCORE_CUTOFFS.keys())
|
1328 | 1329 | output_df['Score'] = output_df[score_components].sum(axis=1)
|
1329 | 1330 |
|
| 1331 | + # Apply score boost for specific symbols |
| 1332 | + output_df['Score'] = output_df['Score'].add( |
| 1333 | + pd.Series( |
| 1334 | + [DRIFT_SCORE_BOOST_AMOUNT if symbol in DRIFT_SCORE_BOOST_SYMBOLS else 0 |
| 1335 | + for symbol in output_df.index], |
| 1336 | + index=output_df.index |
| 1337 | + ) |
| 1338 | + ) |
| 1339 | + |
1330 | 1340 | return output_df
|
1331 | 1341 |
|
1332 | 1342 | def generate_recommendation(row):
|
@@ -2062,7 +2072,7 @@ async def fetch_api_page(session, url: str, retries: int = 5):
|
2062 | 2072 | last_request_time = time.time()
|
2063 | 2073 |
|
2064 | 2074 | try:
|
2065 |
| - async with session.get(url, headers=DRIFT_API_HEADERS, timeout=10) as response: |
| 2075 | + async with session.get(url, headers=DRIFT_DATA_API_HEADERS, timeout=10) as response: |
2066 | 2076 | if response.status != 200:
|
2067 | 2077 | logger.warning(f"API request failed: {url}, status: {response.status}")
|
2068 | 2078 | if attempt < retries - 1:
|
@@ -2104,7 +2114,7 @@ async def fetch_market_trades(session, symbol: str, start_date: datetime, end_da
|
2104 | 2114 |
|
2105 | 2115 | while current_date <= end_date:
|
2106 | 2116 | year, month, day = current_date.year, current_date.month, current_date.day
|
2107 |
| - url = f"{DRIFT_API_BASE_URL}/market/{symbol}/trades/{year}/{month}/{day}?format=json" |
| 2117 | + url = f"{DRIFT_DATA_API_BASE_URL}/market/{symbol}/trades/{year}/{month}/{day}?format=json" |
2108 | 2118 |
|
2109 | 2119 | logger.debug(f"Fetching trades for {symbol} on {year}/{month}/{day}")
|
2110 | 2120 |
|
|
0 commit comments