diff --git a/app/cron_info_text.py b/app/cron_info_text.py index 91b48d3..a42b41e 100644 --- a/app/cron_info_text.py +++ b/app/cron_info_text.py @@ -548,7 +548,51 @@ def save_json(data): "interestCoverage": { "text": "The interest coverage ratio is a measure of the ability of a company to pay its interest expenses. It is calculated by dividing the company's Earnings Before Interest and Taxes (EBIT) by its interest expenses.", "equation": "Interest Coverage Ratio = EBIT / Interest Expense" + }, + "date_expiration": { + "text": "The expiration date indicates how long the option remains valid for exercise. This is particularly important when large investors (whales) are involved in short-term or long-term trades." + }, + "execution_estimate": { + "text": "Select the execution price relative to the bid and ask. The options are: 'Above Ask' (bullish), 'Below Bid' (bearish), 'At Ask' (neutral), 'At Bid' (neutral), and 'At Midpoint' (neutral)." + }, + "moneyness": { + "text": "Select the moneyness of the option. The options are: 'In the Money' (ITM) and 'Out of the Money' (OTM). ITM options have intrinsic value and OTM options are not yet profitable." + }, + "cost_basis": { + "text": "It is the price at which the option was purchased and represents the total investment required to acquire the option. Large premiums (whale activity) can signal significant trading strategies, such as large bets on price movement or hedging strategies." + }, + "put_call": { + "text": "The contract type refers to whether the option is a 'Put' (betting on price decline) or a 'Call' (betting on price rise). This determines the direction of the trade." + }, + "sentiment": { + "text": "Sentiment is determined by the aggressor index. A value of 0.6 or higher indicates a bullish sentiment, below 0.5 indicates a bearish sentiment and 0.5 is considered neutral." + }, + "volume": { + "text": "Volume represents the number of option contracts traded during a specific period. Higher volume typically indicates increased market activity and interest in the option." + }, + "open_interest": { + "text": "Open interest refers to the total number of outstanding option contracts that have not been settled. A rising open interest suggests growing market interest, while a decline may indicate reduced interest or closing positions." + }, + "size": { + "text": "Size refers to the number of contracts in a single trade or order. Larger sizes often indicate significant market activity and can be linked to institutional or whale trading." + }, + "volumeOIRatio": { + "text": "The Volume / Open Interest ratio compares the current trading volume to the total open interest. A higher ratio suggests increased market activity and potential short-term price movement, while a lower ratio indicates less activity relative to outstanding contracts." + }, + "sizeOIRatio": { + "text": "The Size / Open Interest Ratio compares the size of a single trade to the total open interest. A higher ratio may indicate that a large position is being taken relative to the existing contracts, suggesting significant market interest or potential for price movement." + }, + "flowType": { + "text": "Different Flow types such as Repeated flow, which identifies option trades that occur multiple times with the same characteristics (ticker, put/call, strike price, expiration). If the same trade appears more than three times, it's flagged as a repeated flow, indicating significant recurring interest in that specific option." + }, + "option_activity_type": { + "text": "The option activity type indicates the nature of the trade. A 'Sweep' occurs when an order is split across multiple exchanges to quickly execute, often signaling urgency. A 'Trade' refers to a standard option transaction executed on a single exchange." + }, + "underlying_type": { + "text": "The underlying type refers to the asset upon which the option is based. It can be an 'ETF' (Exchange-Traded Fund), which tracks a basket of assets, or a 'Stock,' which represents shares of a single company." } + + } diff --git a/app/cron_options_flow.py b/app/cron_options_flow.py index ee1c906..01608b7 100755 --- a/app/cron_options_flow.py +++ b/app/cron_options_flow.py @@ -1,5 +1,5 @@ import asyncio -import ujson +import orjson import sqlite3 import os from datetime import datetime @@ -36,7 +36,7 @@ def get_symbols(db_path, table_name): async def fetch_options_activity(page): try: data = await asyncio.to_thread(fin.options_activity, date_from=start_date, date_to=end_date, page=page, pagesize=1000) - return ujson.loads(fin.output(data))['option_activity'] + return orjson.loads(fin.output(data))['option_activity'] except Exception as e: print(f"Exception on page {page}: {e}") return [] @@ -95,8 +95,9 @@ async def main(): # Write the final data to a JSON file output_file = "json/options-flow/feed/data.json" - with open(output_file, 'w') as file: - ujson.dump(sorted_data, file) + if len(sorted_data) > 0: + with open(output_file, 'w') as file: + file.write(orjson.dumps(sorted_data).decode("utf-8")) print(f"Data successfully written to {output_file}") diff --git a/app/primary_cron_job.py b/app/primary_cron_job.py index 00c1eba..f5d3aa7 100755 --- a/app/primary_cron_job.py +++ b/app/primary_cron_job.py @@ -104,6 +104,11 @@ def run_shareholders(): if week <= 4: run_command(["python3", "cron_shareholders.py"]) +def run_profile(): + week = datetime.today().weekday() + if week <= 4: + run_command(["python3", "cron_profile.py"]) + def run_share_statistics(): week = datetime.today().weekday() if week <= 4: @@ -314,7 +319,8 @@ def run_threaded(job_func): schedule.every().day.at("08:00").do(run_threaded, run_economy_indicator).tag('economy_indicator_job') schedule.every().day.at("08:00").do(run_threaded, run_cron_insider_trading).tag('insider_trading_job') schedule.every().day.at("08:30").do(run_threaded, run_dividends).tag('dividends_job') -schedule.every().day.at("10:00").do(run_threaded, run_shareholders).tag('shareholders_job') +schedule.every().day.at("09:00").do(run_threaded, run_shareholders).tag('shareholders_job') +schedule.every().day.at("09:30").do(run_threaded, run_profile).tag('profile_job') #schedule.every().day.at("10:30").do(run_threaded, run_sec_filings).tag('sec_filings_job') #schedule.every().day.at("11:00").do(run_threaded, run_executive).tag('executive_job') schedule.every().day.at("12:00").do(run_threaded, run_market_cap).tag('market_cap_josb') @@ -360,7 +366,7 @@ def run_threaded(job_func): schedule.every(2).minutes.do(run_threaded, run_dashboard).tag('dashboard_job') -schedule.every(20).seconds.do(run_threaded, run_if_not_running(run_cron_options_flow, 'options_flow_job')).tag('options_flow_job') +schedule.every(10).seconds.do(run_threaded, run_if_not_running(run_cron_options_flow, 'options_flow_job')).tag('options_flow_job') diff --git a/fastify/app.js b/fastify/app.js index e7aef5d..c28e225 100755 --- a/fastify/app.js +++ b/fastify/app.js @@ -180,7 +180,6 @@ fastify.register(async function (fastify) { fastify.register(async function (fastify) { fastify.get("/options-flow-reader", { websocket: true }, (connection, req) => { - let jsonData; let sendInterval; let lastSentData = [];