From 37dd342e22c039ac423aba577d6db227b5468fb6 Mon Sep 17 00:00:00 2001 From: MuslemRahimi Date: Fri, 27 Dec 2024 22:18:50 +0100 Subject: [PATCH] bugfixing --- .gitignore | 3 +- app/cron_dark_pool_flow.py | 1 - app/cron_sector_flow.py | 89 +++++++++++------- app/main.py | 6 +- app/test.py | 38 ++++++-- .../__pycache__/__init__.cpython-310.pyc | Bin 146 -> 0 bytes .../__pycache__/country_code.cpython-310.pyc | Bin 7487 -> 0 bytes .../__pycache__/country_list.cpython-310.pyc | Bin 7487 -> 0 bytes .../feature_engineering.cpython-310.pyc | Bin 6308 -> 0 bytes app/utils/__pycache__/helper.cpython-310.pyc | Bin 1715 -> 0 bytes 10 files changed, 92 insertions(+), 45 deletions(-) delete mode 100644 app/utils/__pycache__/__init__.cpython-310.pyc delete mode 100644 app/utils/__pycache__/country_code.cpython-310.pyc delete mode 100644 app/utils/__pycache__/country_list.cpython-310.pyc delete mode 100644 app/utils/__pycache__/feature_engineering.cpython-310.pyc delete mode 100644 app/utils/__pycache__/helper.cpython-310.pyc diff --git a/.gitignore b/.gitignore index 3aeec93..0b1b3d0 100755 --- a/.gitignore +++ b/.gitignore @@ -16,4 +16,5 @@ fastify/node_modules pocketbase/* helper.txt env/* -app/ml_models/weights \ No newline at end of file +app/ml_models/weights +app/utils/__pycache__ \ No newline at end of file diff --git a/app/cron_dark_pool_flow.py b/app/cron_dark_pool_flow.py index 225799e..ff3d4b1 100644 --- a/app/cron_dark_pool_flow.py +++ b/app/cron_dark_pool_flow.py @@ -75,7 +75,6 @@ def save_to_daily_file(data, directory): - def get_data(): try: response = requests.get(url, headers=headers, params=querystring) diff --git a/app/cron_sector_flow.py b/app/cron_sector_flow.py index 670f3bd..de0a77f 100644 --- a/app/cron_sector_flow.py +++ b/app/cron_sector_flow.py @@ -53,6 +53,15 @@ def calculate_neutral_premium(data_item): return safe_round(neutral_premium) +def generate_time_intervals(start_time, end_time): + """Generate 1-minute intervals from start_time to end_time.""" + intervals = [] + current_time = start_time + while current_time <= end_time: + intervals.append(current_time.strftime('%Y-%m-%d %H:%M:%S')) + current_time += timedelta(minutes=1) + return intervals + def get_sector_data(): try: url = "https://api.unusualwhales.com/api/market/sector-etfs" @@ -60,6 +69,7 @@ def get_sector_data(): data = response.json().get('data', []) res_list = [] processed_data = [] + for item in data: symbol = item['ticker'] @@ -98,6 +108,13 @@ def get_sector_data(): new_item['price'] = round(quote_data.get('price', 0), 2) new_item['changesPercentage'] = round(quote_data.get('changesPercentage', 0), 2) + #get prem tick data: + if symbol != 'SPY': + prem_tick_history = get_net_prem_ticks(symbol) + #if symbol == 'XLB': + # print(prem_tick_history[10]) + + new_item['premTickHistory'] = prem_tick_history processed_data.append(new_item) return processed_data @@ -105,22 +122,12 @@ def get_sector_data(): print(e) return [] - -def generate_time_intervals(start_time, end_time): - """Generate 1-minute intervals from start_time to end_time.""" - intervals = [] - current_time = start_time - while current_time <= end_time: - intervals.append(current_time.strftime('%Y-%m-%d %H:%M:%S')) - current_time += timedelta(minutes=1) - return intervals - def get_net_prem_ticks(symbol): # Fetch data from the API url = f"https://api.unusualwhales.com/api/stock/{symbol}/net-prem-ticks" response = requests.get(url, headers=headers) data = response.json().get('data', []) - + print(data[0]) # Sort data by date in descending order data = sorted(data, key=lambda x: datetime.fromisoformat(x['date'].replace('Z', '+00:00')), reverse=True) @@ -144,22 +151,41 @@ def get_net_prem_ticks(symbol): # Create a dictionary for fast lookups of existing tape_time data_dict = {entry['tape_time']: entry for entry in data} - # Populate data with 1-minute intervals - populated_data = [] + # Initialize aggregated data with cumulative sums + aggregated_data = {time: { + 'net_call_premium': 0, + 'net_put_premium': 0, + 'net_call_volume': 0, + 'net_put_volume': 0, + 'tape_time': time, + 'close': None + } for time in intervals} + + # Variable to track cumulative sums + cumulative_net_call_premium = 0 + cumulative_net_put_premium = 0 + cumulative_net_call_volume = 0 + cumulative_net_put_volume = 0 + + # Aggregate data for each minute, cumulatively adding values for time in intervals: if time in data_dict: - populated_data.append(data_dict[time]) - else: - populated_data.append({ - 'date': time.split(' ')[0], - 'net_call_premium': None, - 'net_call_volume': None, - 'net_put_premium': None, - 'net_put_volume': None, - 'tape_time': time, - 'close': None - }) - + entry = data_dict[time] + # Add current values to cumulative sums + cumulative_net_call_premium += float(entry.get('net_call_premium', 0)) + cumulative_net_put_premium += float(entry.get('net_put_premium', 0)) + cumulative_net_call_volume += float(entry.get('net_call_volume', 0)) + cumulative_net_put_volume += float(entry.get('net_put_volume', 0)) + + # Set the aggregated values for this minute + aggregated_data[time]['net_call_premium'] = cumulative_net_call_premium + aggregated_data[time]['net_put_premium'] = cumulative_net_put_premium + aggregated_data[time]['net_call_volume'] = cumulative_net_call_volume + aggregated_data[time]['net_put_volume'] = cumulative_net_put_volume + + # Populate data with aggregated results + populated_data = list(aggregated_data.values()) + # Add 'close' values if matches found in price_list matched = False for entry in populated_data: @@ -168,18 +194,17 @@ def get_net_prem_ticks(symbol): entry['close'] = price['close'] matched = True break # Exit inner loop once a match is found + - # Return the populated data if matches exist; otherwise, return an empty list - print(populated_data) return populated_data if matched else [] - def main(): - #sector_data = get_sector_data() - sector_data = [] - net_premium_tick_data = get_net_prem_ticks('XLC') - + ''' + sector_data = get_sector_data() if len(sector_data) > 0: save_json(sector_data) + ''' + get_net_prem_ticks('XLB') + if __name__ == '__main__': main() diff --git a/app/main.py b/app/main.py index 2a1f21e..6e16b26 100755 --- a/app/main.py +++ b/app/main.py @@ -175,9 +175,11 @@ for item in searchbar_data: # Look up the symbol in the stock_screener_data_dict symbol = item['symbol'] item['isin'] = stock_screener_data_dict[symbol]['isin'] - except: + + except Exception as e: item['isin'] = None + etf_set, crypto_set = set(etf_symbols), set(crypto_symbols) @@ -1841,7 +1843,7 @@ async def get_stock( return JSONResponse(content=[]) # Check for exact ISIN match first - exact_match = next((item for item in searchbar_data if item.get("isin") == query), None) + exact_match = next((item for item in searchbar_data if item.get("isin",None) == query), None) if exact_match: return JSONResponse(content=[exact_match]) diff --git a/app/test.py b/app/test.py index 560ece6..52e3d7c 100644 --- a/app/test.py +++ b/app/test.py @@ -5,16 +5,36 @@ import os load_dotenv() api_key = os.getenv('UNUSUAL_WHALES_API_KEY') -querystring = {"limit":"200"} - -url = "https://api.unusualwhales.com/api/darkpool/recent" - +url = 'https://api.unusualwhales.com/api/stock/XLB/net-prem-ticks' headers = { - "Accept": "application/json, text/plain", - "Authorization": api_key + 'Accept': 'application/json', + 'Authorization': api_key } -response = requests.get(url, headers=headers, params=querystring) +response = requests.get(url, headers=headers) +data = response.json()['data'] -print(len(response.json()['data'])) -print(response.json()['data'][0]) \ No newline at end of file +fields_to_sum = [ + "net_call_premium", + "net_call_volume", + "net_put_premium", + "net_put_volume" +] + +result = [] +for idx, e in enumerate(data): + e['net_call_premium'] = float(e['net_call_premium']) + e['net_put_premium'] = float(e['net_put_premium']) + + #e['net_call_volume'] = float(e['net_call_volume']) + #e['net_put_volume'] = float(e['net_put_volume']) + + + if idx != 0: + for field in fields_to_sum: + e[field] += result[idx-1].get(field, 0) + + result.append(e) + +#print(result) +print(result[-1]['net_put_volume']*result[-1]['net_put_premium']*10**(-6)) \ No newline at end of file diff --git a/app/utils/__pycache__/__init__.cpython-310.pyc b/app/utils/__pycache__/__init__.cpython-310.pyc deleted file mode 100644 index 249ad7678866d0949adbf41615379ad7b52a2f01..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 146 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 Awg3PC diff --git a/app/utils/__pycache__/helper.cpython-310.pyc b/app/utils/__pycache__/helper.cpython-310.pyc deleted file mode 100644 index 0e34415ab4fb67810ebffee190f59349ea1d6576..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1715 zcmZuxQE%He5GE-~mKDcw`!t~IAYjWDp>Q0#$(jyB(P3yGiopYx0YUv@s3sjNwj_h1 zm)ekv0mb)ckE(xI*zaezapKIu%+8) z!V#q_-YE-qLIQUM`;mYfSA<&XD3+#-RLGGI4KD;7RqY-cZW@G0Fr@FHXIDVZAf!L& zoM^J3f-UKsYPPU)3LMMXf(r{cD`)5SoC9^{Hb_fLGIw%E@S!~~a9l``Pa8>9@P&HH}c2zgVr_QY}Q-H8@^R<9lfu87fTiO!bV$O zbYG@wICFPj)_3Fju2|WSq30`1+Ny@+4iH6w{2aK3kEeQOTuk*WO{8KVH&&8f7&p_Z zzrKP&I#I@nqhz9`DP2f86yY=|8+VY7B49JKC3SbRhpF@?O37p`F}2MMFR}}p-sp>c zs~i3G{#%!LrIh=RX%_$N{KAkg;@8-p~KjaY?)D2^JLPJ6>dhN|%@?BSY5 zI3719IvQn-fgFvc+8t<$Q;-#`xJ=Fypl&f>cHnx*TT-}my}b^ z)P2lNSwu?qbgHI3%;Bb$fWaavF!=$PS+77NV(=px7aTB$h_shbEP$SSInzaf{6>#K zlWbq>Y|!l$I>6^zm$SD-l-{wqrAz1TqMVc5TCzDWW?s&hRCV+gqVtmdUYpyxve?e; zMRiG*^pr3n%A9a=359w}PDqnvKV1Nt@p}pV6!a%V?+7oq-ja9h5_D&UB`3NzeM6yE zD4Fem#a8azws2s*D9@cY4%9(0UeF5?RA%Qtq@nQjK>9CEer)^wXe9k!3c$$5X(FQJ z%-1RWaLZq1K4Qb)1MvC?ULTsiiDBwhd$!k3Z-vxPCyDU;*S>V9&ZI8F`Np5spD6{35gY{L zy*bDKng@5(7Wh&XB?o_<0&7#*we1OoJ>POPHmq2-HTO zAXG9G#vZFE(WdYgZ F{|`I(zZC!g