add price reaction
This commit is contained in:
parent
f58997f8b7
commit
6110934ca2
@ -9,6 +9,7 @@ import time
|
|||||||
import os
|
import os
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
from ta.momentum import *
|
||||||
from tqdm import tqdm
|
from tqdm import tqdm
|
||||||
import pytz
|
import pytz
|
||||||
|
|
||||||
@ -35,66 +36,76 @@ import pytz
|
|||||||
|
|
||||||
ny_tz = pytz.timezone("America/New_York")
|
ny_tz = pytz.timezone("America/New_York")
|
||||||
|
|
||||||
|
async def compute_rsi(price_history, time_period=14):
|
||||||
|
df_price = pd.DataFrame(price_history)
|
||||||
|
df_price['rsi'] = rsi(df_price['close'], window=time_period)
|
||||||
|
result = df_price.to_dict(orient='records')
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
async def calculate_price_reactions(filtered_data, price_history):
|
async def calculate_price_reactions(filtered_data, price_history):
|
||||||
# Ensure price_history is sorted by date
|
# Ensure price_history is sorted by date
|
||||||
price_history.sort(key=lambda x: datetime.strptime(x['time'], "%Y-%m-%d"))
|
price_history.sort(key=lambda x: x['time'])
|
||||||
|
|
||||||
# Convert price history to a dictionary for quick lookup
|
|
||||||
price_dict = {entry['time']: entry for entry in price_history}
|
|
||||||
|
|
||||||
results = []
|
results = []
|
||||||
|
|
||||||
for earnings in filtered_data:
|
for item in filtered_data:
|
||||||
report_date = earnings['date']
|
report_date = item['date']
|
||||||
report_datetime = ny_tz.localize(datetime.strptime(report_date, "%Y-%m-%d"))
|
|
||||||
|
# Find the index of the report date in the price history
|
||||||
|
report_index = next((i for i, entry in enumerate(price_history) if entry['time'] == report_date), None)
|
||||||
|
if report_index is None:
|
||||||
|
continue # Skip if report date is not found in the price history
|
||||||
|
|
||||||
# Initialize a dictionary for price reactions
|
# Initialize a dictionary for price reactions
|
||||||
price_reactions = {'date': report_date, 'quarter': earnings['quarter'], 'year': earnings['year']}
|
price_reactions = {
|
||||||
|
'date': report_date,
|
||||||
|
'quarter': item['quarter'],
|
||||||
|
'year': item['year'],
|
||||||
|
'time': item['time'],
|
||||||
|
'rsi': int(price_history[report_index]['rsi'])
|
||||||
|
}
|
||||||
|
|
||||||
for offset in [0,1,2]: # Days around earnings
|
for offset in [-4,-3,-2,-1,0,1,2,3,4,6]:
|
||||||
# Calculate initial target date with offset
|
target_index = report_index + offset
|
||||||
target_date = report_datetime - timedelta(days=offset)
|
|
||||||
|
|
||||||
# Adjust target_date to the latest weekday if it falls on a weekend
|
# Ensure the target index is within bounds
|
||||||
if target_date.weekday() == 5: # Saturday
|
if 0 <= target_index < len(price_history):
|
||||||
target_date -= timedelta(days=1) # Move to Friday
|
target_price_data = price_history[target_index]
|
||||||
elif target_date.weekday() == 6: # Sunday
|
previous_index = target_index - 1
|
||||||
target_date -= timedelta(days=2) # Move to Friday
|
|
||||||
|
|
||||||
target_date_str = target_date.strftime("%Y-%m-%d")
|
|
||||||
while target_date_str not in price_dict: # Ensure target_date exists in price_dict
|
|
||||||
target_date -= timedelta(days=1)
|
|
||||||
target_date_str = target_date.strftime("%Y-%m-%d")
|
|
||||||
|
|
||||||
price_data = price_dict[target_date_str]
|
|
||||||
|
|
||||||
# Find the previous day's price data
|
# Ensure the previous index is within bounds
|
||||||
previous_date = target_date - timedelta(days=1)
|
if 0 <= previous_index < len(price_history):
|
||||||
if previous_date.weekday() == 5: # Saturday
|
previous_price_data = price_history[previous_index]
|
||||||
previous_date -= timedelta(days=1) # Move to Friday
|
|
||||||
elif previous_date.weekday() == 6: # Sunday
|
|
||||||
previous_date -= timedelta(days=2) # Move to Friday
|
|
||||||
|
|
||||||
previous_date_str = previous_date.strftime("%Y-%m-%d")
|
# Calculate close price and percentage change
|
||||||
while previous_date_str not in price_dict: # Ensure previous_date exists in price_dict
|
direction = "forward" if offset >= 0 else "backward"
|
||||||
previous_date -= timedelta(days=1)
|
days_key = f"{direction}_{abs(offset)}_days"
|
||||||
previous_date_str = previous_date.strftime("%Y-%m-%d")
|
|
||||||
|
|
||||||
previous_price_data = price_dict[previous_date_str]
|
if offset != 1:
|
||||||
|
price_reactions[f"{days_key}_close"] = target_price_data['close']
|
||||||
|
price_reactions[f"{days_key}_change_percent"] = round(
|
||||||
|
(target_price_data['close'] / previous_price_data['close'] - 1) * 100, 2
|
||||||
|
)
|
||||||
|
|
||||||
|
if offset ==1:
|
||||||
|
price_reactions['open'] = target_price_data['open']
|
||||||
|
price_reactions['high'] = target_price_data['high']
|
||||||
|
price_reactions['low'] = target_price_data['low']
|
||||||
|
price_reactions['close'] = target_price_data['close']
|
||||||
|
|
||||||
|
price_reactions[f"open_change_percent"] = round((target_price_data['open'] / previous_price_data['close'] - 1) * 100, 2)
|
||||||
|
price_reactions[f"high_change_percent"] = round((target_price_data['high'] / previous_price_data['close'] - 1) * 100, 2)
|
||||||
|
price_reactions[f"low_change_percent"] = round((target_price_data['low'] / previous_price_data['close'] - 1) * 100, 2)
|
||||||
|
price_reactions[f"close_change_percent"] = round((target_price_data['close'] / previous_price_data['close'] - 1) * 100, 2)
|
||||||
|
|
||||||
# Calculate close price and percentage change
|
|
||||||
price_reactions[f"{offset+1}_days_close"] = price_data['close']
|
|
||||||
price_reactions[f"{offset+1}_days_change_percent"] = round(
|
|
||||||
(price_data['close'] / previous_price_data['close'] - 1) * 100, 2
|
|
||||||
)
|
|
||||||
|
|
||||||
print(target_date_str, previous_date_str)
|
|
||||||
results.append(price_reactions)
|
results.append(price_reactions)
|
||||||
|
|
||||||
return results
|
return results
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
async def get_past_data(data, ticker, con):
|
async def get_past_data(data, ticker, con):
|
||||||
# Filter data based on date constraints
|
# Filter data based on date constraints
|
||||||
filtered_data = []
|
filtered_data = []
|
||||||
@ -112,7 +123,8 @@ async def get_past_data(data, ticker, con):
|
|||||||
'epsSurprisePercent': round(float(item['eps_surprise_percent'])*100, 2),
|
'epsSurprisePercent': round(float(item['eps_surprise_percent'])*100, 2),
|
||||||
'year': item['period_year'],
|
'year': item['period_year'],
|
||||||
'quarter': item['period'],
|
'quarter': item['period'],
|
||||||
'date': item['date']
|
'date': item['date'],
|
||||||
|
'time': item['time']
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
except:
|
except:
|
||||||
@ -127,11 +139,10 @@ async def get_past_data(data, ticker, con):
|
|||||||
with open(f"json/historical-price/max/{ticker}.json") as file:
|
with open(f"json/historical-price/max/{ticker}.json") as file:
|
||||||
price_history = orjson.loads(file.read())
|
price_history = orjson.loads(file.read())
|
||||||
|
|
||||||
|
price_history = await compute_rsi(price_history)
|
||||||
results = await calculate_price_reactions(filtered_data, price_history)
|
results = await calculate_price_reactions(filtered_data, price_history)
|
||||||
print(filtered_data[0])
|
#print(results[0])
|
||||||
print(results[1])
|
await save_json(results, ticker, 'json/earnings/past')
|
||||||
# Save the updated filtered_data
|
|
||||||
#await save_json(filtered_data, ticker, 'json/earnings/past')
|
|
||||||
|
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
@ -162,7 +173,7 @@ try:
|
|||||||
cursor.execute("PRAGMA journal_mode = wal")
|
cursor.execute("PRAGMA journal_mode = wal")
|
||||||
cursor.execute("SELECT DISTINCT symbol FROM stocks WHERE symbol NOT LIKE '%.%' AND symbol NOT LIKE '%-%'")
|
cursor.execute("SELECT DISTINCT symbol FROM stocks WHERE symbol NOT LIKE '%.%' AND symbol NOT LIKE '%-%'")
|
||||||
stock_symbols = [row[0] for row in cursor.fetchall()]
|
stock_symbols = [row[0] for row in cursor.fetchall()]
|
||||||
stock_symbols = ['AMD']
|
#stock_symbols = ['AMD']
|
||||||
|
|
||||||
asyncio.run(run(stock_symbols, con))
|
asyncio.run(run(stock_symbols, con))
|
||||||
|
|
||||||
|
|||||||
@ -32,7 +32,7 @@ etf_con.close()
|
|||||||
|
|
||||||
|
|
||||||
# Define start and end dates for historical data
|
# Define start and end dates for historical data
|
||||||
start_date = datetime.strptime('2023-01-01', '%Y-%m-%d')
|
start_date = datetime.strptime('2025-01-01', '%Y-%m-%d')
|
||||||
end_date = datetime.now()
|
end_date = datetime.now()
|
||||||
|
|
||||||
# Directory to save the JSON files
|
# Directory to save the JSON files
|
||||||
|
|||||||
37
app/main.py
37
app/main.py
@ -3906,14 +3906,8 @@ async def get_next_earnings(data:TickerData, api_key: str = Security(get_api_key
|
|||||||
except:
|
except:
|
||||||
res = {}
|
res = {}
|
||||||
|
|
||||||
try:
|
|
||||||
with open(f"json/earnings/past/{ticker}.json", 'rb') as file:
|
|
||||||
past_earnings = orjson.loads(file.read())
|
|
||||||
except:
|
|
||||||
past_earnings = []
|
|
||||||
|
|
||||||
final_res = {'next': res, 'past': past_earnings}
|
data = orjson.dumps(res)
|
||||||
data = orjson.dumps(final_res)
|
|
||||||
compressed_data = gzip.compress(data)
|
compressed_data = gzip.compress(data)
|
||||||
|
|
||||||
redis_client.set(cache_key, compressed_data)
|
redis_client.set(cache_key, compressed_data)
|
||||||
@ -3954,6 +3948,35 @@ async def get_surprise_earnings(data:TickerData, api_key: str = Security(get_api
|
|||||||
headers={"Content-Encoding": "gzip"}
|
headers={"Content-Encoding": "gzip"}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@app.post("/price-action-earnings")
|
||||||
|
async def get_data(data:TickerData, api_key: str = Security(get_api_key)):
|
||||||
|
ticker = data.ticker.upper()
|
||||||
|
cache_key = f"price-action-earnings-{ticker}"
|
||||||
|
cached_result = redis_client.get(cache_key)
|
||||||
|
if cached_result:
|
||||||
|
return StreamingResponse(
|
||||||
|
io.BytesIO(cached_result),
|
||||||
|
media_type="application/json",
|
||||||
|
headers={"Content-Encoding": "gzip"}
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
with open(f"json/earnings/past/{ticker}.json", 'rb') as file:
|
||||||
|
res = orjson.loads(file.read())
|
||||||
|
except:
|
||||||
|
res = []
|
||||||
|
|
||||||
|
data = orjson.dumps(res)
|
||||||
|
compressed_data = gzip.compress(data)
|
||||||
|
|
||||||
|
redis_client.set(cache_key, compressed_data)
|
||||||
|
redis_client.expire(cache_key,3600*60)
|
||||||
|
|
||||||
|
return StreamingResponse(
|
||||||
|
io.BytesIO(compressed_data),
|
||||||
|
media_type="application/json",
|
||||||
|
headers={"Content-Encoding": "gzip"}
|
||||||
|
)
|
||||||
|
|
||||||
@app.post("/info-text")
|
@app.post("/info-text")
|
||||||
async def get_info_text(data:InfoText, api_key: str = Security(get_api_key)):
|
async def get_info_text(data:InfoText, api_key: str = Security(get_api_key)):
|
||||||
parameter = data.parameter
|
parameter = data.parameter
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user