| |
| """utils.py |
| |
| Automatically generated by Colab. |
| |
| Original file is located at |
| https://colab.research.google.com/drive/1RyRghhbleQJ01USX_0O4uUALsuFM10hJ |
| """ |
|
|
| |
| |
|
|
| import pandas as pd |
| import plotly.graph_objects as go |
| import re |
| import numpy as np |
| import traceback |
|
|
| def get_nested_value(data_dict, keys, default=None): |
| """Safely get a value from a nested dictionary or list.""" |
| current_level = data_dict |
| for key in keys: |
| if isinstance(current_level, dict) and key in current_level: |
| current_level = current_level[key] |
| elif isinstance(current_level, list) and isinstance(key, int) and 0 <= key < len(current_level): |
| current_level = current_level[key] |
| else: |
| return default |
| return current_level |
|
|
| def parse_numeric_string(value_str, default=None): |
| """Attempts to parse numeric values from strings, handling $, %, and commas.""" |
| if not isinstance(value_str, str): |
| |
| if isinstance(value_str, (int, float)): |
| return value_str |
| |
| return default |
| try: |
| |
| cleaned_str = re.sub(r'[$,%]', '', value_str).strip() |
| return float(cleaned_str) |
| except (ValueError, TypeError): |
| |
| return default |
|
|
|
|
| def create_empty_figure(title="No Data Available"): |
| """Creates an empty Plotly figure with a title.""" |
| fig = go.Figure() |
| fig.update_layout( |
| title=title, |
| xaxis={'visible': False}, |
| yaxis={'visible': False}, |
| annotations=[{ |
| 'text': title, |
| 'xref': 'paper', 'yref': 'paper', |
| 'showarrow': False, 'font': {'size': 16} |
| }] |
| ) |
| return fig |
|
|
| def process_timeseries_chart(chart_data, value_col_name='Value'): |
| """ |
| Processes QuantConnect timeseries chart data like [[timestamp, value, ...], ...]. |
| Assumes timestamp is in SECONDS. Extracts the second element as the value. |
| Returns a DataFrame with 'Time' (datetime) index and value_col_name. |
| Handles potential errors during processing. |
| """ |
| |
| if not chart_data or not isinstance(chart_data, list): |
| |
| return pd.DataFrame(columns=['Time', value_col_name]).set_index('Time') |
|
|
| |
| if not chart_data[0] or not isinstance(chart_data[0], (list, tuple)) or len(chart_data[0]) < 2: |
| |
| return pd.DataFrame(columns=['Time', value_col_name]).set_index('Time') |
|
|
| try: |
| |
| |
| processed_data = [ |
| [item[0], item[1]] for item in chart_data |
| if isinstance(item, (list, tuple)) and len(item) >= 2 and item[0] is not None and item[1] is not None |
| ] |
|
|
| |
| if not processed_data: |
| |
| return pd.DataFrame(columns=['Time', value_col_name]).set_index('Time') |
|
|
| |
| df = pd.DataFrame(processed_data, columns=['Time_Raw', value_col_name]) |
|
|
| |
| df['Time_Raw'] = pd.to_numeric(df['Time_Raw'], errors='coerce') |
| df.dropna(subset=['Time_Raw'], inplace=True) |
| if df.empty: return pd.DataFrame(columns=['Time', value_col_name]).set_index('Time') |
|
|
|
|
| |
| df['Time'] = pd.to_datetime(df['Time_Raw'], unit='s', errors='coerce') |
| df.dropna(subset=['Time'], inplace=True) |
| if df.empty: return pd.DataFrame(columns=['Time', value_col_name]).set_index('Time') |
|
|
|
|
| |
| df[value_col_name] = pd.to_numeric(df[value_col_name], errors='coerce') |
| df.dropna(subset=[value_col_name], inplace=True) |
| if df.empty: return pd.DataFrame(columns=['Time', value_col_name]).set_index('Time') |
|
|
|
|
| |
| df = df.set_index('Time') |
|
|
| |
| if not isinstance(df.index, pd.DatetimeIndex): |
| print(f"Warning: Index is not DatetimeIndex for {value_col_name} after setting. Attempting conversion.") |
| df.index = pd.to_datetime(df.index, errors='coerce') |
| df.dropna(inplace=True) |
| if df.empty: return pd.DataFrame(columns=['Time', value_col_name]).set_index('Time') |
|
|
|
|
| |
| if df.index.tz is None: |
| df = df.tz_localize('UTC') |
| elif df.index.tz != 'UTC': |
| df = df.tz_convert('UTC') |
|
|
| |
| return df[[value_col_name]].sort_index() |
|
|
| except Exception as e: |
| print(f"Error creating/processing DataFrame for {value_col_name}: {e}") |
| traceback.print_exc() |
| |
| return pd.DataFrame(columns=['Time', value_col_name]).set_index('Time') |