Dooratre commited on
Commit
d05d6ed
·
verified ·
1 Parent(s): bb7bae5

Create timeframe.py

Browse files
Files changed (1) hide show
  1. timeframe.py +232 -0
timeframe.py ADDED
@@ -0,0 +1,232 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import requests
2
+ import json
3
+ import time
4
+ from datetime import datetime, timedelta
5
+ import pandas as pd
6
+ from tabulate import tabulate
7
+
8
+ def fetch_financial_data(symbol="USDCAD=X", start_date=None, end_date=None, interval="1m", days_to_fetch=1):
9
+ """
10
+ Fetch and process financial data from Yahoo Finance.
11
+
12
+ Parameters:
13
+ symbol (str): The ticker symbol (e.g., "USDCAD=X" for USD/CAD exchange rate)
14
+ start_date (datetime): Start date for the data (optional, defaults to 1 day ago if not provided)
15
+ end_date (datetime): End date for the data (optional, defaults to current time if not provided)
16
+ interval (str): Data interval - Options include "1m", "5m", "15m", "30m", "60m", "1d", "1wk", "1mo"
17
+ days_to_fetch (int): Number of days to fetch data for if end_date is not specified
18
+
19
+ Returns:
20
+ dict: A dictionary containing:
21
+ - 'data': pandas DataFrame with the processed financial data
22
+ - 'meta': dictionary with meta information
23
+ - 'table': formatted table string
24
+ - 'meta_info': formatted meta information string
25
+ - 'stats': formatted summary statistics string
26
+ - 'success': boolean indicating if the operation was successful
27
+ - 'message': status message
28
+ """
29
+ # Set default dates if not provided
30
+ if start_date is None:
31
+ start_date = datetime.now() - timedelta(days=days_to_fetch)
32
+ if end_date is None:
33
+ end_date = datetime.now()
34
+
35
+ result = {
36
+ 'data': None,
37
+ 'meta': None,
38
+ 'table': None,
39
+ 'meta_info': None,
40
+ 'stats': None,
41
+ 'success': False,
42
+ 'message': ""
43
+ }
44
+
45
+ try:
46
+ # Convert datetime to Unix timestamp
47
+ period1 = int(time.mktime(start_date.timetuple()))
48
+ period2 = int(time.mktime(end_date.timetuple()))
49
+
50
+ # Construct the URL
51
+ url = f"https://query2.finance.yahoo.com/v8/finance/chart/{symbol}"
52
+
53
+ # Parameters for the request
54
+ params = {
55
+ "period1": period1,
56
+ "period2": period2,
57
+ "interval": interval,
58
+ "includePrePost": "true",
59
+ "events": "div|split|earn",
60
+ "lang": "en-US",
61
+ "region": "US",
62
+ "source": "cosaic"
63
+ }
64
+
65
+ # Headers to mimic a browser request
66
+ headers = {
67
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36"
68
+ }
69
+
70
+ # Make the request
71
+ response = requests.get(url, params=params, headers=headers)
72
+
73
+ if response.status_code == 200:
74
+ data = response.json()
75
+
76
+ # Process the data
77
+ if not data or 'chart' not in data or 'result' not in data['chart'] or not data['chart']['result']:
78
+ result['message'] = "No valid data to process"
79
+ return result
80
+
81
+ # Extract the relevant data
82
+ api_result = data['chart']['result'][0]
83
+ meta = api_result['meta']
84
+ timestamps = api_result['timestamp']
85
+ quotes = api_result['indicators']['quote'][0]
86
+
87
+ # Create a DataFrame
88
+ df = pd.DataFrame({
89
+ 'timestamp': timestamps,
90
+ 'open': quotes['open'],
91
+ 'high': quotes['high'],
92
+ 'low': quotes['low'],
93
+ 'close': quotes['close'],
94
+ 'volume': quotes['volume']
95
+ })
96
+
97
+ # Convert timestamps to datetime
98
+ df['timestamp'] = pd.to_datetime(df['timestamp'], unit='s')
99
+
100
+ # Calculate additional metrics
101
+ df['range'] = df['high'] - df['low']
102
+ df['change'] = df['close'] - df['open']
103
+ df['change_pct'] = (df['change'] / df['open'] * 100).round(3)
104
+
105
+ # Mark if the candle is bullish (close > open) or bearish (close < open)
106
+ df['trend'] = ['Bullish' if c > o else 'Bearish' if c < o else 'Neutral'
107
+ for c, o in zip(df['close'], df['open'])]
108
+
109
+ # Format the DataFrame for display
110
+ display_df = df.copy()
111
+
112
+ # Format the timestamp
113
+ display_df['Date'] = display_df['timestamp'].dt.strftime('%Y-%m-%d')
114
+ display_df['Time'] = display_df['timestamp'].dt.strftime('%H:%M:%S')
115
+
116
+ # Round numerical values to 4 decimal places
117
+ for col in ['open', 'high', 'low', 'close', 'range']:
118
+ if col in display_df.columns:
119
+ display_df[col] = display_df[col].round(4)
120
+
121
+ # Add color indicators for trend (will be visible in HTML output)
122
+ display_df['Change'] = display_df['change'].round(4)
123
+ display_df['% Change'] = display_df['change_pct'].round(2).astype(str) + '%'
124
+
125
+ # Select columns for display
126
+ table_df = display_df[['Date', 'Time', 'open', 'high', 'low', 'close',
127
+ 'range', 'Change', '% Change', 'trend']]
128
+
129
+ # Rename columns for better readability
130
+ table_df.columns = ['Date', 'Time', 'Open', 'High', 'Low', 'Close',
131
+ 'Range', 'Change', '% Change', 'Trend']
132
+
133
+ # Create the table using tabulate
134
+ table = tabulate(table_df, headers='keys', tablefmt='fancy_grid', showindex=False)
135
+
136
+ # Add a title
137
+ title = f"{symbol} Price Data ({interval} interval)"
138
+ title_line = "=" * len(title)
139
+ formatted_table = f"\n{title_line}\n{title}\n{title_line}\n\n{table}"
140
+
141
+ # Format meta information
142
+ meta_str = "META INFORMATION\n===============\n"
143
+
144
+ # Extract key information
145
+ key_info = {
146
+ 'Currency': meta.get('currency'),
147
+ 'Symbol': meta.get('symbol'),
148
+ 'Exchange Name': meta.get('exchangeName'),
149
+ 'Full Exchange Name': meta.get('fullExchangeName'),
150
+ 'Instrument Type': meta.get('instrumentType'),
151
+ 'First Trade Date': datetime.fromtimestamp(meta.get('firstTradeDate', 0)).strftime('%Y-%m-%d') if 'firstTradeDate' in meta else 'N/A',
152
+ 'Regular Market Time': datetime.fromtimestamp(meta.get('regularMarketTime', 0)).strftime('%Y-%m-%d %H:%M:%S') if 'regularMarketTime' in meta else 'N/A',
153
+ 'Timezone': meta.get('timezone'),
154
+ 'Exchange Timezone': meta.get('exchangeTimezoneName'),
155
+ 'Regular Market Price': meta.get('regularMarketPrice'),
156
+ '52 Week High': meta.get('fiftyTwoWeekHigh'),
157
+ '52 Week Low': meta.get('fiftyTwoWeekLow'),
158
+ 'Day High': meta.get('regularMarketDayHigh'),
159
+ 'Day Low': meta.get('regularMarketDayLow'),
160
+ 'Volume': meta.get('regularMarketVolume'),
161
+ 'Long Name': meta.get('longName'),
162
+ 'Short Name': meta.get('shortName'),
163
+ 'Previous Close': meta.get('previousClose'),
164
+ 'Scale': meta.get('scale'),
165
+ 'Price Hint': meta.get('priceHint')
166
+ }
167
+
168
+ # Format the key_info as a string
169
+ for key, value in key_info.items():
170
+ if isinstance(value, float):
171
+ meta_str += f"{key}: {value:.4f}\n"
172
+ else:
173
+ meta_str += f"{key}: {value}\n"
174
+
175
+ # Add trading period information
176
+ if 'currentTradingPeriod' in meta:
177
+ meta_str += "\nCURRENT TRADING PERIOD\n=====================\n"
178
+ for period_type, period_info in meta['currentTradingPeriod'].items():
179
+ start_time = datetime.fromtimestamp(period_info.get('start', 0)).strftime('%Y-%m-%d %H:%M:%S')
180
+ end_time = datetime.fromtimestamp(period_info.get('end', 0)).strftime('%Y-%m-%d %H:%M:%S')
181
+ meta_str += f"{period_type.capitalize()} Period: {start_time} to {end_time} ({period_info.get('timezone', 'Unknown')})\n"
182
+
183
+ # Generate summary statistics
184
+ stats = {
185
+ 'Symbol': symbol,
186
+ 'Long Name': meta.get('longName', symbol),
187
+ 'Period Start': df['timestamp'].min().strftime("%Y-%m-%d %H:%M:%S"),
188
+ 'Period End': df['timestamp'].max().strftime("%Y-%m-%d %H:%M:%S"),
189
+ 'Data Points': len(df),
190
+ 'Opening Price': df['open'].iloc[0],
191
+ 'Closing Price': df['close'].iloc[-1],
192
+ 'Current Price': meta.get('regularMarketPrice', df['close'].iloc[-1]),
193
+ 'Overall Change': df['close'].iloc[-1] - df['open'].iloc[0],
194
+ 'Overall % Change': ((df['close'].iloc[-1] / df['open'].iloc[0]) - 1) * 100,
195
+ 'Highest Price': df['high'].max(),
196
+ 'Lowest Price': df['low'].min(),
197
+ 'Average Price': df[['open', 'high', 'low', 'close']].mean().mean(),
198
+ 'Price Range': df['high'].max() - df['low'].min(),
199
+ 'Day High (Meta)': meta.get('regularMarketDayHigh'),
200
+ 'Day Low (Meta)': meta.get('regularMarketDayLow'),
201
+ '52 Week High': meta.get('fiftyTwoWeekHigh'),
202
+ '52 Week Low': meta.get('fiftyTwoWeekLow'),
203
+ 'Bullish Candles': (df['trend'] == 'Bullish').sum(),
204
+ 'Bearish Candles': (df['trend'] == 'Bearish').sum(),
205
+ 'Neutral Candles': (df['trend'] == 'Neutral').sum()
206
+ }
207
+
208
+ # Format the stats as a string
209
+ stats_str = "SUMMARY STATISTICS\n==================\n"
210
+ for key, value in stats.items():
211
+ if isinstance(value, float):
212
+ stats_str += f"{key}: {value:.4f}\n"
213
+ else:
214
+ stats_str += f"{key}: {value}\n"
215
+
216
+ # Populate result dictionary
217
+ result['data'] = df
218
+ result['meta'] = meta
219
+ result['table'] = formatted_table
220
+ result['meta_info'] = meta_str
221
+ result['stats'] = stats_str
222
+ result['success'] = True
223
+ result['message'] = f"Successfully processed {len(df)} data points."
224
+
225
+ return result
226
+ else:
227
+ result['message'] = f"Failed to fetch data: Status code {response.status_code}"
228
+ return result
229
+
230
+ except Exception as e:
231
+ result['message'] = f"Error: {str(e)}"
232
+ return result