AlirezaX2 commited on
Commit
84da62d
·
1 Parent(s): a80106c
Files changed (3) hide show
  1. Dockerfile +17 -0
  2. requirements.txt +7 -0
  3. src/app.py +153 -0
Dockerfile ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.11
2
+
3
+ WORKDIR /code
4
+
5
+ COPY ./requirements.txt /code/requirements.txt
6
+ RUN python3 -m pip install --no-cache-dir --upgrade pip
7
+ RUN python3 -m pip install --no-cache-dir --upgrade -r /code/requirements.txt
8
+
9
+ COPY . .
10
+
11
+ CMD ["panel", "serve", "/code/src/app.py", "--address", "0.0.0.0", "--port", "7860", "--allow-websocket-origin", "*"]
12
+
13
+ RUN mkdir /.cache
14
+ RUN chmod 777 /.cache
15
+ RUN mkdir .chroma
16
+ RUN chmod 777 .chroma
17
+
requirements.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ yfinance
2
+ panel
3
+ hvplot
4
+ bokeh
5
+ requests
6
+ python-dotenv
7
+
src/app.py ADDED
@@ -0,0 +1,153 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pandas as pd
2
+ import numpy as np
3
+
4
+ import requests
5
+ import json
6
+
7
+ import os
8
+
9
+ import time
10
+ import calendar
11
+
12
+ from datetime import datetime
13
+ from datetime import date, timedelta
14
+
15
+ import hvplot as hv
16
+ import holoviews as hvs
17
+ import panel as pn
18
+ import hvplot.pandas
19
+
20
+ from dotenv import load_dotenv
21
+
22
+ # Specify the path to your .env file
23
+ # dotenv_path = '/../.env'
24
+ # Polygon_API_Key = os.getenv('Polygon_API_Key')
25
+
26
+ Polygon_API_Key = os.environ.get('mypolgonAPI')
27
+
28
+ def generate_option_contract_id(ticker, exp_date, option_type, strike_price):
29
+ """
30
+ Generate a concise contract identifier string based on input values.
31
+
32
+ Args:
33
+ ticker (str): The stock ticker symbol.
34
+ exp_date (str): The expiration date of the option (format: "YYYY-MM-DD").
35
+ option_type (str): The type of option ("C" for call or "P" for put).
36
+ strike_price (float): The strike price of the option.
37
+
38
+ Returns:
39
+ str: The generated option contract identifier string.
40
+ """
41
+ # Format expiration date (remove dashes and take last 6 digits)
42
+ formatted_exp_date = str(exp_date).replace('-', '')[-6:]
43
+
44
+ # Format strike price (remove decimal point and zero-pad)
45
+ formatted_strike_price = f"{int(strike_price * 1000):08d}" # Convert to integer and zero-pad to 5 digits
46
+
47
+ # Determine option type label (use uppercase)
48
+ option_label = option_type.upper()
49
+
50
+ # Generate the contract identifier string
51
+ contract_id = f"{ticker}{formatted_exp_date}{option_label}{formatted_strike_price}"
52
+
53
+ return contract_id # Ensure the total length does not exceed 11 characters
54
+
55
+ def extract_raw_data(contract , interval, timeframe, startdate ,enddate):
56
+ url = f"https://api.polygon.io/v2/aggs/ticker/O:{contract}/range/{interval}/{timeframe}/{startdate}/{enddate}?apiKey={Polygon_API_Key}"
57
+
58
+ headers={"Authorization": f"Bearer {Polygon_API_Key}"}
59
+
60
+ resp = requests.get(url , headers=headers)
61
+ if resp.status_code == 200:
62
+ # print(resp.text)
63
+ if json.loads(resp.text)['resultsCount']>0:
64
+ data = json.loads(resp.text)['results']
65
+ df = pd.DataFrame(data)
66
+ # df['t'] = pd.to_datetime(df['t'], unit='ms')
67
+ df['UNIXTIME'] = pd.to_datetime(df['t'], unit='ms', utc=True).map(lambda x: x.tz_convert('America/New_York'))
68
+ return df
69
+ # print(resp.status_code)
70
+ # raise Exception(f"API request failed with status code: {resp.status_code}")
71
+ return pd.DataFrame() #Empty Dataframe
72
+
73
+ def _transform_data(raw_data: pd.DataFrame):
74
+ data = raw_data[["UNIXTIME", "o", "h", "l", "c", "v"]].copy(deep=True).rename(columns={
75
+ "UNIXTIME": "time",
76
+ "o": "open",
77
+ "h": "high",
78
+ "l": "low",
79
+ "c": "close",
80
+ "v": "volume",
81
+ })
82
+ # data['time_start'] = data.time # rectangles start (no offset for 1-minute)
83
+ # data['time_end'] = data.time # rectangles end (no offset for 1-minute)
84
+ # data['positive'] = ((data.close - data.open) > 0).astype(int)
85
+ # return data
86
+
87
+ # Calculate delta (minimum difference) between timestamps in seconds
88
+ delta = data['time'].diff().dt.total_seconds().min() /2 # Adjust for missing values if needed
89
+
90
+ data['time_start'] = data['time'] - pd.Timedelta(seconds=delta) # rectangles start (no offset for 1-minute)
91
+ data['time_end'] = data['time'] + pd.Timedelta(seconds=delta) # rectangles end with delta
92
+
93
+ data['positive'] = ((data.close - data.open) > 0).astype(int)
94
+ return data
95
+
96
+ def get_last_friday():
97
+ today = date.today()
98
+ # Check if today is Friday, if not go back to previous friday
99
+ last_friday = today - timedelta(days = (today.weekday() - calendar.FRIDAY) % 7, weeks=(today.weekday() == calendar.FRIDAY))
100
+ return last_friday
101
+
102
+
103
+ ticker = pn.widgets.AutocompleteInput(name='Ticker', options=['NVDA','TSLA', 'AMZN' , 'MSFT' , 'AAPL' , 'GOOG' , 'AMD'] , placeholder='Write Ticker here همین جا',value='ALL', restrict=False)
104
+ ticker.value = "NVDA"
105
+
106
+ exp_date = pn.widgets.DatePicker(
107
+ name ="Expiry Date",
108
+ description='Select a Date',
109
+ start= date.today() - timedelta(days=365 * 2)
110
+ )
111
+ exp_date.value = get_last_friday() #date.today() - timedelta(days= 2)
112
+
113
+ startdate = pn.widgets.DatePicker(
114
+ name ="Start Date",
115
+ description='Select a Date',
116
+ start= date.today() - timedelta(days=365 * 2)
117
+ )
118
+ startdate.value = get_last_friday()
119
+
120
+
121
+ enddate = pn.widgets.DatePicker(
122
+ name ="End Date",
123
+ description='Select a Date',
124
+ start= date.today() - timedelta(days=365 * 2)
125
+ )
126
+ enddate.value = get_last_friday()
127
+
128
+ option_type = pn.widgets.Select(name='Option Type', options=['C', 'P'])
129
+ option_type.value = 'C'
130
+
131
+ strike_price = pn.widgets.IntInput(name='IntInput', value=850, step=10, start=0, end=1000)
132
+
133
+ interval = pn.widgets.Select(name='Time Frame (min)', options=['1', '5', '10'])
134
+ timeframe = "minute" #The only supported resolutions are minute|hour|day|week|month|quarter|year"0
135
+
136
+ def make_candle_stick(ticker , exp_date, option_type, strike_price, interval ,startdate , enddate ):
137
+ contract = generate_option_contract_id(ticker, exp_date, option_type, strike_price)
138
+ raw_data = extract_raw_data(contract , interval, timeframe, startdate ,enddate)
139
+ if raw_data.shape[0]!=0:
140
+ data = _transform_data(raw_data=raw_data)
141
+ _delta = np.median(np.diff(data.time))
142
+ candlestick = hvs.Segments(data, kdims=['time', 'low', 'time', 'high']) * hvs.Rectangles(data, kdims=['time_start','open', 'time_end', 'close'], vdims=['positive'])
143
+ candlestick = candlestick.redim.label(Low='Values')
144
+ 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)) ,
145
+ data.hvplot(x="time", y="volume", kind="line", responsive=True, height=200).opts( show_grid=True) )
146
+ # data.hvplot(y="volume", kind="bar", responsive=True, height=200) )
147
+ else:
148
+ candlechart = pn.Column(pn.widgets.LoadingSpinner(value=True, size=20, name='Loading...'))
149
+ # time.sleep(60)
150
+ return candlechart
151
+
152
+ 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)
153
+ pn.Row(pn.Column(ticker, exp_date , option_type , strike_price , interval , timeframe , startdate , enddate), bound_plot).servable(title="Intraday Options Price - Pattern Detection")