| import pandas as pd |
| import numpy as np |
|
|
| import requests |
| import json |
|
|
| import os |
|
|
| import time |
| import calendar |
|
|
| from datetime import datetime |
| from datetime import date, timedelta |
|
|
| import hvplot as hv |
| import holoviews as hvs |
| import panel as pn |
| import hvplot.pandas |
|
|
| pn.extension('bokeh', template='bootstrap') |
|
|
| from dotenv import load_dotenv |
|
|
| |
| |
| |
|
|
| Polygon_API_Key = os.environ.get('mypolgonAPI') |
|
|
| def generate_option_contract_id(ticker, exp_date, option_type, strike_price): |
| """ |
| Generate a concise contract identifier string based on input values. |
| |
| Args: |
| ticker (str): The stock ticker symbol. |
| exp_date (str): The expiration date of the option (format: "YYYY-MM-DD"). |
| option_type (str): The type of option ("C" for call or "P" for put). |
| strike_price (float): The strike price of the option. |
| |
| Returns: |
| str: The generated option contract identifier string. |
| """ |
| |
| formatted_exp_date = str(exp_date).replace('-', '')[-6:] |
|
|
| |
| formatted_strike_price = f"{int(strike_price * 1000):08d}" |
|
|
| |
| option_label = option_type.upper() |
|
|
| |
| contract_id = f"{ticker}{formatted_exp_date}{option_label}{formatted_strike_price}" |
|
|
| return contract_id |
|
|
| @pn.cache |
| def extract_raw_data(contract , interval, timeframe, startdate ,enddate): |
| url = f"https://api.polygon.io/v2/aggs/ticker/O:{contract}/range/{interval}/{timeframe}/{startdate}/{enddate}?apiKey={Polygon_API_Key}" |
|
|
| headers={"Authorization": f"Bearer {Polygon_API_Key}"} |
|
|
| resp = requests.get(url , headers=headers) |
| if resp.status_code == 200: |
| |
| if json.loads(resp.text)['resultsCount']>0: |
| data = json.loads(resp.text)['results'] |
| df = pd.DataFrame(data) |
| |
| df['UNIXTIME'] = pd.to_datetime(df['t'], unit='ms', utc=True).map(lambda x: x.tz_convert('America/New_York')) |
| return df |
| |
| |
| return pd.DataFrame() |
|
|
| def _transform_data(raw_data: pd.DataFrame): |
| data = raw_data[["UNIXTIME", "o", "h", "l", "c", "v"]].copy(deep=True).rename(columns={ |
| "UNIXTIME": "time", |
| "o": "open", |
| "h": "high", |
| "l": "low", |
| "c": "close", |
| "v": "volume", |
| }) |
| |
| |
| |
| |
|
|
| |
| delta = data['time'].diff().dt.total_seconds().min() /2 |
|
|
| data['time_start'] = data['time'] - pd.Timedelta(seconds=delta) |
| data['time_end'] = data['time'] + pd.Timedelta(seconds=delta) |
|
|
| data['positive'] = ((data.close - data.open) > 0).astype(int) |
| return data |
|
|
| def get_last_friday(): |
| today = date.today() |
| |
| last_friday = today - timedelta(days = (today.weekday() - calendar.FRIDAY) % 7, weeks=(today.weekday() == calendar.FRIDAY)) |
| return last_friday |
|
|
| def get_next_friday(): |
| today = date.today() |
| |
| days_until_next_friday = (calendar.FRIDAY - today.weekday() + 7) % 7 |
| next_friday = today + timedelta(days=days_until_next_friday) |
| return next_friday |
|
|
|
|
| ticker = pn.widgets.AutocompleteInput(name='Ticker', options=['NVDA','TSLA', 'AMZN' , 'MSFT' , 'AAPL' , 'GOOG' , 'AMD' ,'META' ,'AVGO','JPM','LLY','NVO','TSM','V', 'ASML','SMCI','CVX','JNJ','ARM','COST','WDAY'] , placeholder='Write Ticker here همین جا',value='ALL', restrict=False) |
| ticker.value = "NVDA" |
|
|
| exp_date = pn.widgets.DatePicker( |
| name ="Expiry Date", |
| description='Select a Date', |
| start= date.today() - timedelta(days=365 * 2) |
| ) |
| exp_date.value = get_next_friday() |
|
|
| startdate = pn.widgets.DatePicker( |
| name ="Start Date", |
| description='Select a Date', |
| start= date.today() - timedelta(days=365 * 2) |
| ) |
| startdate.value = get_last_friday() |
|
|
|
|
| enddate = pn.widgets.DatePicker( |
| name ="End Date", |
| description='Select a Date', |
| start= date.today() - timedelta(days=365 * 2) |
| ) |
| enddate.value = get_next_friday() |
|
|
| option_type = pn.widgets.Select(name='Option Type', options=['C', 'P']) |
| option_type.value = 'C' |
|
|
| strike_price = pn.widgets.IntInput(name='Strike', value=140, step=10, start=0, end=1000) |
|
|
| interval = pn.widgets.Select(name='Time Frame (min)', options=['1', '5', '10']) |
| timeframe = "minute" |
|
|
| def make_candle_stick(ticker , exp_date, option_type, strike_price, interval ,startdate , enddate ): |
| contract = generate_option_contract_id(ticker, exp_date, option_type, strike_price) |
| raw_data = extract_raw_data(contract , interval, timeframe, startdate ,enddate) |
| if raw_data.shape[0]!=0: |
| data = _transform_data(raw_data=raw_data) |
| _delta = np.median(np.diff(data.time)) |
| candlestick = hvs.Segments(data, kdims=['time', 'low', 'time', 'high']) * hvs.Rectangles(data, kdims=['time_start','open', 'time_end', 'close'], vdims=['positive']) |
| candlestick = candlestick.redim.label(Low='Values') |
| candlechart = pn.Column(candlestick.opts(hvs.opts.Rectangles(color='positive', cmap=['red', 'green'], responsive=True), hvs.opts.Segments(color='black', height=800, responsive=True , show_grid=True, title=contract)) , |
| data.hvplot(x="time", y="volume", kind="line", responsive=True, height=200).opts( show_grid=True) ) |
| |
| else: |
| candlechart = pn.Column(pn.widgets.LoadingSpinner(value=True, size=20, name='Loading...')) |
| |
| return candlechart |
|
|
| bound_plot = pn.bind( make_candle_stick, ticker = ticker, exp_date=exp_date , option_type=option_type ,strike_price=strike_price, interval=interval , startdate=startdate,enddate=enddate) |
| pn.Row(pn.Column(ticker, exp_date , option_type , strike_price , interval , startdate , enddate), bound_plot).servable(title="Intraday Options Price - Pattern Detection") |
|
|