A world class data provider that is extremely cost effective. Most of the code on this site is powered by Norgate Data
Python
AmiBroker
MQL 4/5
Tradingview
Python
Dashboard
Chart Gallery
Backtesting – Backtrader
News
Screeners
Trading Strategies
Dashboard
#Performance Overview PrettyTable
import yfinance as yf
import pandas as pd
import numpy as np
from datetime import datetime, timedelta
import matplotlib.pyplot as plt
import matplotlib.ticker as mtick
from matplotlib.ticker import FuncFormatter
import seaborn as sns
import warnings
# Suppress runtime warnings
warnings.filterwarnings("ignore", category=RuntimeWarning)
warnings.filterwarnings("ignore", message="The 'unit' keyword in TimedeltaIndex construction is deprecated")
# Function to get the nearest date from a series of dates
def get_nearest_date(series, target):
nearest = min(series, key=lambda x: abs(x - target))
return nearest
# Define your watchlists
watchlists = {
'main_watchlist': ['ES=F', '^TNX','DX-Y.NYB', 'GC=F', 'CL=F'],
'main_stock_exchanges': ['^GSPC','^DJI','^IXIC','^VIX', '^FTSE', '^GDAXI', '^N225', '^HSI', '000001.SS', '^STI', '^AORD'],
'main_futures' : ['ES=F','ZN=F', 'GC=F', 'SI=F','PL=F','CL=F', 'HG=F', 'NG=F', 'ZC=F', 'KE=F', 'CC=F', 'KC=F'],
'main_fx' : ['EURUSD=X', 'JPY=X', 'GBPUSD=X', 'AUDUSD=X', 'CNY=X', 'EURJPY=X','EURGBP=X' ],
'main_us_treasury -yield' : ['^IRX', '^FVX', '^TNX', '^TYX' ],
'main_crypto': ['BTC-USD', 'ETH-USD', 'ADA-USD', 'SOL-USD'],
'main_Mike_Stocks': ['AAPL', 'MSFT', 'GOOG', 'AMZN', 'TSLA', 'NVDA','META','GME'],
}
# Ticker to name mapping (extend this dictionary to include all your symbols)
descriptions = {
'ES=F' : 'S&P 500 Future',
'^GSPC' : 'S&P 500 Index',
'^DJI' : 'Dow Jones Industrial Index',
'^IXIC' : 'Nasdaq 100 Index',
'^VIX' : 'VIX Index',
"TLT" : '20 Plus Year Treasury Bond ETF',
'ZN=F' : '10 Year T-Note (USA)',
'PL=F' : 'Platinum',
'BTC-USD': 'Bitcoin',
'ETH-USD': 'Ethereum',
'ADA-USD': 'Cardano',
'SOL-USD': 'Solana',
'DX-Y.NYB': 'US Dollar Index',
'GC=F' : 'Gold',
'CL=F' : 'Crude Oil',
'^FTSE' : 'FTSE 100 Index',
'^GDAXI' : 'DAX Index',
'^N225' : 'Nikkei 225 Index',
'^HSI' : 'Hang Seng Index',
'000001.SS' : 'Shanghai Composite Index',
'^STI' : 'Straits Times Index',
'^AORD' : 'Australian Stock Exchange',
'EURUSD=X' : 'EUR/USD',
'JPY=X' : 'JPY/USD',
'GBPUSD=X' : 'GBP/USD',
'AUDUSD=X' : 'AUD/USD',
'CNY=X' : 'CNY/USD',
'EURJPY=X' : 'EUR/JPY',
'EURGBP=X' : 'EUR/GBP',
'SI=F' : 'Silver',
'HG=F' : 'Copper',
'NG=F' : 'Natural Gas',
'ZC=F' : 'Corn',
'KE=F' : 'Wheat',
'CC=F' : 'Cocoa',
'KC=F' : 'Coffee',
'^IRX' : '3 mnth Treasury yield',
'^FVX' : '5 yr Treasury yield',
'^TNX' : '10 yr Treasury yield',
'^TYX' : '30 yr Treasury yield',
'BTC-USD': 'Bitcoin',
'ETH-USD': 'Ethereum',
'ADA-USD': 'Cardano',
'SOL-USD': 'Solana',
'AAPL' : 'Apple',
'MSFT' : 'Microsoft',
'GOOG' : 'Google',
'AMZN' : 'Amazon',
'TSLA' : 'Tesla',
'BABA' : 'Alibaba',
'NVDA' : 'NVIDIA',
'META' : 'Meta',
'GME' : 'GameStop'
}
# Download and process data for each watchlist
for watchlist_name, symbols in watchlists.items():
print(f"Processing {watchlist_name}...")
# Get the current UTC datetime
current_utc_datetime = datetime.utcnow()
# Extract just the date part
#end_date = current_utc_datetime.date()
# Define the end date as today and start date as 20 years ago
end_date = datetime.today()
start_date = end_date - timedelta(days=252*20) # Approximately 10 years of trading days
# Download data
data = yf.download(symbols, start=start_date, end=end_date)['Adj Close']
# Forward fill missing data points
data.ffill(inplace=True)
# Fill any remaining NaN values with 0
data.fillna(0, inplace=True)
# Compute returns
returns = data.pct_change().dropna()
# Compute different period returns
returns_daily = data.pct_change().dropna()
returns_weekly = data.resample('W').ffill().pct_change().dropna()
returns_monthly = data.resample('ME').ffill().pct_change().dropna()
returns_yearly = data.resample('YE').ffill().pct_change().dropna()
# Compute statistics
stats_daily = {'mean': returns_daily.mean(), 'std': returns_daily.std()}
stats_weekly = {'mean': returns_weekly.mean(), 'std': returns_weekly.std()}
stats_monthly = {'mean': returns_monthly.mean(), 'std': returns_monthly.std()}
stats_yearly = {'mean': returns_yearly.mean(), 'std': returns_yearly.std()}
# Convert the index to datetime if it's not already
if not isinstance(data.index, pd.DatetimeIndex):
data.index = pd.to_datetime(data.index)
def get_last_business_day(target_date):
"""
Find the last business day for a given date. This function assumes that 'data' is a global DataFrame object with
a DateTimeIndex.
Parameters:
target_date (datetime): The target date from which we want to find the last business day.
Returns:
datetime: The last business day.
"""
# Ensure the DataFrame index is a DateTimeIndex.
if not isinstance(data.index, pd.DatetimeIndex):
raise TypeError("DataFrame index must be a DatetimeIndex")
# Create a date range ending with your target date, only including the business days in your data.
# This line creates a DatetimeIndex of all business days in your dataset up to 'target_date'.
all_business_days = pd.date_range(start=data.index.min(), end=target_date, freq='B')
# Find the intersection of this business days index with your data's actual days to account for holidays/missing days.
valid_business_days = data.index.intersection(all_business_days)
if valid_business_days.empty:
raise ValueError("No business days found in the date range. Check your data's date coverage.")
# The last valid business day is the maximum of this intersection.
last_business_day = valid_business_days.max()
return last_business_day
# Calculate Date Offsets for Current Week, Month, and Year
end_date = datetime.now()
curr_week_start = get_nearest_date(data.index, end_date - timedelta(days=end_date.weekday() + 3)) # Previous Friday
# Find the first day of the current month and subtract one day to get into the previous month
first_day_current_month = end_date.replace(day=1)
last_day_previous_month = first_day_current_month - timedelta(days=1)
# Now find the last business day in the previous month
curr_month_start = get_last_business_day(last_day_previous_month)
# Find the first day of the current year and subtract one day to get into the previous year
first_day_current_year = end_date.replace(month=1, day=1)
last_day_previous_year = first_day_current_year - timedelta(days=1)
# Now find the last business day in the previous year
curr_year_start = get_last_business_day(last_day_previous_year)
# Prepare data for final DataFrame (for each symbol in the current watchlist)
df_data = []
for symbol in symbols:
price = f"{data[symbol].iloc[-1]:.2f}" # Convert to string and keep 2 decimal places
one_day_return = returns[symbol].iloc[-1] # this is the current day's return
# Check if the return is zero and, if so, use the previous valid return.
if one_day_return == 0:
# Find the last non-zero return. This involves a bit of looping.
# We start with the day before and go backwards until we find a non-zero return.
idx = -2 # Start with the day before
while True:
one_day_return = returns[symbol].iloc[idx]
if one_day_return != 0 or idx < -len(returns[symbol]):
break # Stop if we find a non-zero return or reach the start of the series
idx -= 1 # Move one day further back
# Then convert the return to a percentage for display
one_day_return_percentage = f"{one_day_return * 100:.2f}" # same here
week_return = f"{((data[symbol].iloc[-1] / data[symbol].loc[curr_week_start]) - 1) * 100:.2f}" # and here
month_return = f"{((data[symbol].iloc[-1] / data[symbol].loc[curr_month_start]) - 1) * 100:.2f}" # and so on
year_return = f"{((data[symbol].iloc[-1] / data[symbol].loc[curr_year_start]) - 1) * 100:.2f}"
df_data.append({
'Symbol': symbol,
'Description': descriptions[symbol],
'Price': price,
'1 Day %': one_day_return_percentage,
'Week %': week_return,
'Month %': month_return,
'Year %': year_return,
})
# Create a DataFrame for the current watchlist
df = pd.DataFrame(df_data)
def color_map(idx, col_name):
symbol = df.at[idx, 'Symbol']
# Define a variable to capture the correct return, whether it's the current day's or a non-zero previous one.
return_value = None
# Determine the return value based on the column being processed.
if col_name == '1 Day %':
return_value = returns_daily[symbol].iloc[-1]
# If the return is zero, fetch the last non-zero return (similar to the earlier part of your code).
if return_value == 0:
idx = -2 # Start with the day before
while True:
previous_return = returns_daily[symbol].iloc[idx]
if previous_return != 0 or idx < -len(returns_daily[symbol]):
return_value = previous_return # Set the actual return to the found non-zero return.
break
idx -= 1 # Move one day further back
# Now, calculate the Z-score using the actual return value.
z_score = (return_value - stats_daily['mean'][symbol]) / stats_daily['std'][symbol]
elif col_name == 'Week %':
return_value = (data[symbol].iloc[-1] / data[symbol].loc[curr_week_start]) - 1
z_score = (return_value - stats_weekly['mean'][symbol]) / stats_weekly['std'][symbol]
elif col_name == 'Month %':
return_value = (data[symbol].iloc[-1] / data[symbol].loc[curr_month_start]) - 1
z_score = (return_value - stats_monthly['mean'][symbol]) / stats_monthly['std'][symbol]
elif col_name == 'Year %':
return_value = (data[symbol].iloc[-1] / data[symbol].loc[curr_year_start]) - 1
z_score = (return_value - stats_yearly['mean'][symbol]) / stats_yearly['std'][symbol]
else:
return 'white' # If the column is not a return column.
# Now we apply the logic for coloring based on the sign of the return value and its z-score.
if return_value > 0: # Positive return.
if z_score > 1:
return 'darkgreen'
elif z_score > 0.5:
return 'lightgreen'
else:
return 'white'
else: # Negative return.
if z_score < -1:
return 'darkred'
elif z_score < -0.5:
return 'lightcoral'
else:
return 'white'
return determined_color # This is whatever color your logic determines based on the Z-score.
# Prepare colors DataFrame
colors_df = pd.DataFrame(index=df.index, columns=df.columns)
for idx, row in df.iterrows():
for col in df.columns:
colors_df.at[idx, col] = color_map(idx, col)
# Define column widths and figure size
col_widths = [0.05, 0.12, 0.05, 0.05, 0.05, 0.05, 0.05] # Adjust as needed
num_rows = len(symbols)
row_height = 0.6 # Adjust as needed
fig_height = num_rows * row_height
# Create the figure and table
fig, ax = plt.subplots(figsize=(14, fig_height)) # Adjust the overall size here
ax.axis('off')
ax.set_title(f'{watchlist_name}', fontsize=16, fontweight='bold')
# Add last updated date and time
last_updated = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
ax.text(0, 1.02, f'Last Updated: {last_updated}', transform=ax.transAxes, fontsize=9, va='bottom', ha='left')
# Create the table
tbl = ax.table(cellText=df.values, colLabels=df.columns, bbox=[0, 0, 1, 1],
cellColours=colors_df.values, colWidths=col_widths)
tbl.auto_set_font_size(False)
tbl.set_fontsize(13) # Adjust the font size
# Modify the cell height
cellDict = tbl.get_celld()
for i in range(len(df.columns)):
cellDict[(0, i)].set_height(.012) # Adjust the height
for j in range(len(df.index)):
cellDict[(j+1, i)].set_height(.01) # Adjust the height
# Make headers bold
for (row, col), cell in tbl.get_celld().items():
if row == 0:
cell.set_text_props(fontweight='bold')
# Formatting the end_date as a string in the format 'YYYY-MM-DD'
formatted_end_date = end_date.strftime('%Y-%m-%d')
# Save the figure to a file
fig.tight_layout()
# You will need to use your own directory to save to
plt.savefig(f'G:/My Drive/WPS2N/dashboard/{watchlist_name}.png', bbox_inches='tight')
# Include the formatted_end_date in the file name for Newsletter
plt.savefig(f'G:/My Drive/WPS2N/newsletter/{watchlist_name}_{formatted_end_date}.png', bbox_inches='tight')
plt.show()
import yfinance as yf
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import FuncFormatter
from datetime import datetime
# Define the start and end date
start_date = datetime(datetime.today().year, 1, 1) # Start of the year
# Extract just the date part
end_date = current_utc_datetime.date()
symbol_descriptions = {
'ES=F' : 'S&P 500 Future',
'^GSPC' : 'S&P 500 Index',
'^DJI' : 'Dow Jones Industrial Index',
'^IXIC' : 'Nasdaq 100 Index',
'^VIX' : 'VIX Index',
"TLT" : '20 Plus Year Treasury Bond ETF',
'ZN=F' : '10 Year T-Note (USA)',
'PL=F' : 'Platinum',
'BTC-USD': 'Bitcoin',
'ETH-USD': 'Ethereum',
'ADA-USD': 'Cardano',
'SOL-USD': 'Solana',
'DX-Y.NYB': 'US Dollar Index',
'GC=F' : 'Gold',
'CL=F' : 'Crude Oil',
'^FTSE' : 'FTSE 100 Index',
'^GDAXI' : 'DAX Index',
'^N225' : 'Nikkei 225 Index',
'^HSI' : 'Hang Seng Index',
'000001.SS' : 'Shanghai Composite Index',
'^STI' : 'Straits Times Index',
'^AORD' : 'Australian Index',
'EURUSD=X' : 'EUR/USD',
'JPY=X' : 'JPY/USD',
'GBPUSD=X' : 'GBP/USD',
'AUDUSD=X' : 'AUD/USD',
'CNY=X' : 'CNY/USD',
'EURJPY=X' : 'EUR/JPY',
'EURGBP=X' : 'EUR/GBP',
'SI=F' : 'Silver',
'HG=F' : 'Copper',
'NG=F' : 'Natural Gas',
'ZC=F' : 'Corn',
'KE=F' : 'Wheat',
'CC=F' : 'Cocoa',
'KC=F' : 'Coffee',
'^IRX' : '3 mnth Treasury',
'^FVX' : '5 yr Treasury',
'^TNX' : '10 yr Treasury',
'^TYX' : '30 yr Treasury',
'BTC-USD': 'Bitcoin',
'ETH-USD': 'Ethereum',
'ADA-USD': 'Cardano',
'SOL-USD': 'Solana',
}
# Define the groups
groups = [
{
"name": "Main_Watchlist", # Customize the group name
"symbols": ['ES=F', "ZN=F",'DX-Y.NYB', 'GC=F','CL=F'],
},
{
"name": "World_Indices", # Customize the group name
"symbols": ['^GSPC', '^FTSE', '^GDAXI', '^N225', '^HSI', '000001.SS'], # Customize the symbols
},
{
"name": "Futures", # Customize the group name
"symbols": ['SI=F', 'HG=F', 'NG=F', 'ZC=F', 'KE=F', 'CC=F', 'KC=F'],
},
{
"name": "FX", # Customize the group name
"symbols": ['DX-Y.NYB', 'EURUSD=X', 'JPY=X', 'GBPUSD=X', 'AUDUSD=X', 'CNY=X'],
},
{
"name": "US_Treasury Yields", # Customize the group name
"symbols": ['^IRX', '^FVX', '^TNX', '^TYX' ],
},
{
"name": "Crypto", # Customize the group name
"symbols": ['BTC-USD', 'ETH-USD', 'ADA-USD', 'SOL-USD'], # Customize the symbols
},
]
def plot_hbar_for_group(group, symbol_descriptions):
group_name = group["name"]
group_symbols = group["symbols"]
# Initialize an empty DataFrame for this group
group_data = pd.DataFrame()
# Download data for each symbol and concatenate into a single DataFrame
for symbol in group_symbols:
data = yf.download(symbol, start=start_date, end=end_date)
if not data.empty: # Check if data is not empty
adj_close = data['Adj Close'].dropna() # Ensure no NaN values
group_data[symbol] = adj_close
# Skip group if no data was downloaded
if group_data.empty:
print(f"No data available for symbols in the group '{group_name}'. Skipping...")
return
# Forward fill missing data points and fill any remaining NaN values with 0
data.ffill(inplace=True)
group_data.fillna(0, inplace=True)
# Calculate the daily percentage change and cumulative product
returns = group_data.pct_change().replace([np.inf, -np.inf], np.nan).dropna()
# Replace -100% returns with 0%, I encountered this issue with the data from the world indices
returns[returns == -1.0] = 0.0
performance = (returns + 1).cumprod() - 1
# Prepare data for the horizontal bar chart
ytd_performance = performance.iloc[-1] # get the last row, i.e., the latest date
ytd_performance = ytd_performance.sort_values() # sort by performance
# Modify the index to include descriptions instead of just symbols
ytd_descriptions = [symbol_descriptions.get(symbol, symbol) for symbol in ytd_performance.index]
ytd_performance.index = ytd_descriptions
# Create colors based on performance (positive in green, negative in red)
colors = ['#FF341C' if x < 0 else '#009900' for x in ytd_performance]
# Set the thickness of your bars
bar_thickness = 0.65 # you can adjust the thickness by setting this value
# Generate the positions for the left side of each bar (since it's a horizontal bar chart)
y_positions = range(len(ytd_performance))
# Create a figure and a subplot
fig, ax = plt.subplots(figsize=(12, len(group_symbols) * 0.5)) # adjust the height depending on the number of symbols
# Plot horizontal bar chart directly with matplotlib (to control bar thickness)
ax.barh(y_positions, ytd_performance, height=bar_thickness, color=colors)
# Customize the axes and grid
ax.set_title(f'YTD Performance for {group_name}')
ax.set_xlabel('Cumulative Returns YTD')
ax.axvline(0, color='grey', linewidth=0.5) # add a vertical line at x=0
# Set the y-ticks to be the middle of each bar, and set their labels
ax.set_yticks([pos for pos in y_positions])
ax.set_yticklabels([symbol_descriptions.get(symbol, symbol) for symbol in ytd_performance.index])
# Format x-ticks as percentages
def percentage_formatter(x, pos):
"""Convert the decimal to a percentage."""
return f"{x * 100:.0f}%" # You can customize the number of decimal places by changing `.0f` to, say, `.2f` for two decimal places.
# Now apply the formatter to the x-axis
ax.xaxis.set_major_formatter(FuncFormatter(percentage_formatter))
ax.grid(axis='x', linestyle='--', alpha=0.7)
# Add last updated date and time
last_updated = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
ax.text(0, 1.02, f'Last Updated: {last_updated}', transform=ax.transAxes, fontsize=9, va='bottom', ha='left')
# Save the figure (you might want to adjust the path and filename)
fig.tight_layout()
# remember to change the directory
plt.savefig(f'G:/My Drive/WPS2N/dashboard/{group_name.replace(" ", "_")}_YTD_HBAR.png')
plt.show()
# Loop through each group and create a bar chart
for group in groups:
plot_hbar_for_group(group, symbol_descriptions) # pass the descriptions to your function
# Define the start and end date
start_date = datetime(datetime.today().year, 1, 1) # Start of the year
# Extract just the date part
end_date = current_utc_datetime.date()
# Define the groups
groups = [
{
"name": "Main_Watchlist", # Customize the group name
"symbols": ['ES=F', "ZN=F",'DX-Y.NYB', 'GC=F', 'CL=F'],
},
{
"name": "World_Indices", # Customize the group name
"symbols": ['^GSPC', '^FTSE', '^GDAXI', '^N225', '^HSI', '000001.SS'], # Customize the symbols
},
{
"name": "Futures", # Customize the group name
"symbols": ['SI=F', 'HG=F', 'NG=F', 'ZC=F', 'KE=F', 'CC=F', 'KC=F'],
},
{
"name": "FX", # Customize the group name
"symbols": ['DX-Y.NYB', 'EURUSD=X', 'JPY=X', 'GBPUSD=X', 'AUDUSD=X', 'CNY=X'],
},
{
"name": "US_Treasury Yields", # Customize the group name
"symbols": ['^IRX', '^FVX', '^TNX', '^TYX' ],
},
{
"name": "Crypto", # Customize the group name
"symbols": ['BTC-USD', 'ETH-USD', 'ADA-USD', 'SOL-USD'], # Customize the symbols
},
]
# Colors for the plot lines
green_tone = "#009900"
red_tone = "#FF341C"
def plot_for_group(group):
group_name = group["name"]
group_symbols = group["symbols"]
# Initialize an empty DataFrame for this group
group_data = pd.DataFrame()
# Download data for each symbol and concatenate into a single DataFrame
for symbol in group_symbols:
data = yf.download(symbol, start=start_date, end=end_date)
if not data.empty: # Check if data is not empty
adj_close = data['Adj Close'].dropna() # Ensure no NaN values
group_data[symbol] = adj_close
# Skip group if no data was downloaded
if group_data.empty:
print(f"No data available for symbols in the group '{group_name}'. Skipping...")
return
# Forward fill missing data points and fill any remaining NaN values with 0
group_data.ffill(inplace=True)
group_data.fillna(0, inplace=True)
# Calculate the daily percentage change and cumulative product
returns = group_data.pct_change().replace([np.inf, -np.inf], np.nan).dropna()
performance = (returns + 1).cumprod() - 1
symbol_descriptions = {
'ES=F' : 'S&P 500 Future',
'^GSPC' : 'S&P 500 Index',
'^DJI' : 'Dow Jones Industrial Index',
'^IXIC' : 'Nasdaq 100 Index',
'^VIX' : 'VIX Index',
"TLT" : '20 Plus Year Treasury Bond ETF',
'ZN=F' : '10 Year T-Note (USA)',
'PL=F' : 'Platinum',
'BTC-USD': 'Bitcoin',
'ETH-USD': 'Ethereum',
'ADA-USD': 'Cardano',
'SOL-USD': 'Solana',
'DX-Y.NYB': 'US Dollar Index',
'GC=F' : 'Gold',
'CL=F' : 'Crude Oil',
'^FTSE' : 'FTSE 100 Index',
'^GDAXI' : 'DAX Index',
'^N225' : 'Nikkei 225 Index',
'^HSI' : 'Hang Seng Index',
'000001.SS' : 'Shanghai Composite Index',
'^STI' : 'Straits Times Index',
'^AORD' : 'Australian Index',
'EURUSD=X' : 'EUR/USD',
'JPY=X' : 'JPY/USD',
'GBPUSD=X' : 'GBP/USD',
'AUDUSD=X' : 'AUD/USD',
'CNY=X' : 'CNY/USD',
'EURJPY=X' : 'EUR/JPY',
'EURGBP=X' : 'EUR/GBP',
'SI=F' : 'Silver',
'HG=F' : 'Copper',
'NG=F' : 'Natural Gas',
'ZC=F' : 'Corn',
'KE=F' : 'Wheat',
'CC=F' : 'Cocoa',
'KC=F' : 'Coffee',
'^IRX' : '3 mnth Treasury',
'^FVX' : '5 yr Treasury',
'^TNX' : '10 yr Treasury',
'^TYX' : '30 yr Treasury',
'BTC-USD': 'Bitcoin',
'ETH-USD': 'Ethereum',
'ADA-USD': 'Cardano',
'SOL-USD': 'Solana',
}
# Create a figure and a subplot
fig, ax = plt.subplots(figsize=(14, 6))
# Plotting each symbol
for symbol in group_symbols:
if symbol in performance: # Check if symbol is in the DataFrame
symbol_data = performance[symbol]
color = green_tone if symbol_data.iloc[-1] > 0 else red_tone
ax.plot(symbol_data.index, symbol_data, label=symbol, color=color)
# Get the description from the dictionary, defaulting to the symbol if not found
symbol_description = symbol_descriptions.get(symbol, symbol)
# Get the last point of the data to annotate
last_point_y = symbol_data.iloc[-1]
last_point_x = symbol_data.index[-1]
if pd.notnull(last_point_y): # Check if it's not NaN
# Creating the annotation for each line's last point
ax.annotate(f"{symbol_description}: {last_point_y:.2%}",
xy=(last_point_x, last_point_y), xycoords='data',
xytext=(40, 30), textcoords='offset points',
ha='left', va="center",
arrowprops=dict(arrowstyle="->", connectionstyle="angle3,angleA=0,angleB=45", color=color),
color=color)
# Customize the axes and grid
ax.set_title(f'YTD Performance for {group_name}')
ax.set_xlabel('Date')
ax.set_ylabel('Cumulative Returns')
ax.yaxis.set_major_formatter(mtick.PercentFormatter(1.0))
ax.grid(False)
ax.axhline(0, color='black', linewidth=0.5, linestyle='--')
# Add last updated date and time
last_updated = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
ax.text(0, 1.02, f'Last Updated: {last_updated}', transform=ax.transAxes, fontsize=9, va='bottom', ha='left')
# Save the figure
fig.tight_layout()
# Remember to change the directory
filename = f"G:/My Drive/WPS2N/dashboard/{group_name.replace(' ', '_')}_YTD_Performance.png"
plt.savefig(filename)
plt.show()
print(f"Plot saved as {filename}")
# Iterating over each group and plotting
for group in groups:
plot_for_group(group)
# Define different groups of symbols for comparison
grouped_compare_symbols = [
['DX-Y.NYB', 'GC=F', 'TLT', 'HG=F', '^GSPC'],
['CL=F', 'BTC-USD'],
['EURUSD=X', 'JPY=X', 'GBPUSD=X', 'AUDUSD=X', 'CNY=X']
]
# Define the symbols and their descriptions dictionary.
symbol_descriptions = {
'^GSPC' : 'S&P 500 Index',
'^IXIC' : 'Nasdaq 100 Index',
"TLT" : '20+ yr Treasury Bonds',
'BTC-USD': 'Bitcoin',
'DX-Y.NYB': 'US Dollar Index',
'GC=F' : 'Gold',
'CL=F' : 'Crude Oil',
'^FTSE' : 'FTSE 100 Index',
'^GDAXI' : 'DAX Index',
'^N225' : 'Nikkei 225 Index',
'^HSI' : 'Hang Seng Index',
'000001.SS' : 'Shanghai Index',
'^STI' : 'Straits Times Index',
'^AORD' : 'Australian Index',
'EURUSD=X' : 'EUR/USD',
'JPY=X' : 'JPY/USD',
'GBPUSD=X' : 'GBP/USD',
'AUDUSD=X' : 'AUD/USD',
'CNY=X' : 'CNY/USD',
'SI=F' : 'Silver',
'HG=F' : 'Copper',
'NG=F' : 'Natural Gas',
}
# Use the current date as the end date
end_date = datetime.now()
# Download stock data - including all symbols for efficiency
all_symbols = [symbol for group in grouped_compare_symbols for symbol in group] # Flatten the list of lists
data = yf.download(all_symbols, start="2015-01-01", end=end_date)['Adj Close']
# Calculate daily returns
daily_returns = data.pct_change()
# Define the rolling window (in trading days, typically 252 trading days in a year)
rolling_window = 250
# The number of trading days per year (used for annualization)
trading_days_per_year = 252
# For each group of compare_symbols, calculate rolling volatility and create a plot
for i, compare_group in enumerate(grouped_compare_symbols):
# Calculate the rolling standard deviation (volatility) for each symbol in the current group
# and adjust it to percentage format by multiplying by 100
rolling_volatility = daily_returns[compare_group].rolling(window=rolling_window).std() * (trading_days_per_year ** 0.5) * 100
# Create a new figure for each group
fig, ax = plt.subplots(figsize=(15, 8))
# Plot the rolling volatility of each symbol in the current group
for symbol in compare_group:
# Retrieve the description from the dictionary, defaulting to the symbol if not found
description = symbol_descriptions.get(symbol, symbol)
# Plot with the description as the label
ax.plot(rolling_volatility.index, rolling_volatility[symbol], label=description)
# Customize the plot
ax.set_title(f'Annualized Rolling {rolling_window}-Day Volatility', fontsize=16, fontweight='bold')
ax.set_ylabel('Volatility (%)', fontsize=14)
ax.set_xlabel('Date', fontsize=14)
ax.legend(loc='upper right', fontsize=12)
ax.grid(False)
# Add last updated date and time
last_updated = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
ax.text(0, 1.02, f'Last Updated: {last_updated}', transform=ax.transAxes, fontsize=9, va='bottom', ha='left')
# Save and show the plot
plt.tight_layout()
filename = f'G:/My Drive/WPS2N/volatility/Rolling_Volatility_Group_{i+1}.png'
plt.savefig(filename)
plt.show()
# Define the symbols and their descriptions
symbol_descriptions = {
'^GSPC' : 'S&P 500 Index',
'^IXIC' : 'Nasdaq 100 Index',
"TLT" : '20+ yr Treasury Bonds',
'BTC-USD': 'Bitcoin',
'DX-Y.NYB': 'US Dollar Index',
'GC=F' : 'Gold',
'CL=F' : 'Crude Oil',
'^FTSE' : 'FTSE 100 Index',
'^GDAXI' : 'DAX Index',
'^N225' : 'Nikkei 225 Index',
'^HSI' : 'Hang Seng Index',
'000001.SS' : 'Shanghai Index',
'^STI' : 'Straits Times Index',
'^AORD' : 'Australian Index',
'EURUSD=X' : 'EUR/USD',
'JPY=X' : 'JPY/USD',
'GBPUSD=X' : 'GBP/USD',
'AUDUSD=X' : 'AUD/USD',
'CNY=X' : 'CNY/USD',
'SI=F' : 'Silver',
'HG=F' : 'Copper',
'NG=F' : 'Natural Gas',
}
# List of symbols
symbols = list(symbol_descriptions.keys())
# Use the current date as the end date
end_date = datetime.now()
# Download stock data
data = yf.download(symbols, start="2000-01-01", end=end_date)['Adj Close']
# Calculate daily returns
daily_returns = data.pct_change()
# Calculate correlation matrix
correlation_matrix = daily_returns.corr()
# Create a list of descriptions in the order of the correlation matrix's columns
ordered_labels = [symbol_descriptions[symbol] for symbol in correlation_matrix.columns]
# Create a heatmap of the correlation matrix
plt.figure(figsize=(16, 14))
# Generate a heatmap with annotations and capture the axis.
ax = sns.heatmap(correlation_matrix, annot=True, fmt=".2f", cmap='coolwarm', linewidths=.5, annot_kws={"size": 8, "weight": "bold"},
xticklabels=ordered_labels, yticklabels=ordered_labels) # Use descriptions as labels
plt.xticks(rotation=90, fontsize=8, fontweight='bold') # Rotate and set fontsize for x labels (may need adjustment)
plt.yticks(rotation=0, fontsize=8, fontweight='bold') # Set fontsize for y labels
# Add last updated date and time
last_updated = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
ax.text(0, 1.00, f'Last Updated: {last_updated}', transform=ax.transAxes, fontsize=9, va='bottom', ha='left')
# Show plot
plt.title('Daily Correlation Matrix - since 2000', fontsize=18, fontweight='bold')
plt.tight_layout()
plt.savefig(f'G:/My Drive/WPS2N/correlations/Correlation_Matrix2000.png')
plt.show()
# Define the symbols and their descriptions
symbol_descriptions = {
'^GSPC' : 'S&P 500 Index',
'^IXIC' : 'Nasdaq 100 Index',
"TLT" : '20+ yr Treasury Bonds',
'BTC-USD': 'Bitcoin',
'DX-Y.NYB': 'US Dollar Index',
'GC=F' : 'Gold',
'CL=F' : 'Crude Oil',
'^FTSE' : 'FTSE 100 Index',
'^GDAXI' : 'DAX Index',
'^N225' : 'Nikkei 225 Index',
'^HSI' : 'Hang Seng Index',
'000001.SS' : 'Shanghai Index',
'^STI' : 'Straits Times Index',
'^AORD' : 'Australian Index',
'EURUSD=X' : 'EUR/USD',
'JPY=X' : 'JPY/USD',
'GBPUSD=X' : 'GBP/USD',
'AUDUSD=X' : 'AUD/USD',
'CNY=X' : 'CNY/USD',
'SI=F' : 'Silver',
'HG=F' : 'Copper',
'NG=F' : 'Natural Gas',
}
# List of symbols
symbols = list(symbol_descriptions.keys())
# Use the current date as the end date
end_date = datetime.now()
# Download stock data
data = yf.download(symbols, start="2013-01-01", end=end_date)['Adj Close']
# Calculate daily returns
daily_returns = data.pct_change()
# Calculate correlation matrix
correlation_matrix = daily_returns.corr()
# Create a list of descriptions in the order of the correlation matrix's columns
ordered_labels = [symbol_descriptions[symbol] for symbol in correlation_matrix.columns]
# Create a heatmap of the correlation matrix
plt.figure(figsize=(16, 14))
# Generate a heatmap with annotations and capture the axis.
ax = sns.heatmap(correlation_matrix, annot=True, fmt=".2f", cmap='coolwarm', linewidths=.5, annot_kws={"size": 8, "weight": "bold"},
xticklabels=ordered_labels, yticklabels=ordered_labels) # Use descriptions as labels
plt.xticks(rotation=90, fontsize=8, fontweight='bold') # Rotate and set fontsize for x labels (may need adjustment)
plt.yticks(rotation=0, fontsize=8, fontweight='bold') # Set fontsize for y labels
# Add last updated date and time
last_updated = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
ax.text(0, 1.00, f'Last Updated: {last_updated}', transform=ax.transAxes, fontsize=9, va='bottom', ha='left')
# Show plot
plt.title('Daily Correlation Matrix - since 2013', fontsize=18, fontweight='bold')
plt.tight_layout()
plt.savefig(f'G:/My Drive/WPS2N/correlations/Correlation_Matrix2013.png')
plt.show()
# Define base symbols
base_symbols = ['^GSPC', 'GC=F', 'TLT', 'DX-Y.NYB'] # Removed the duplicate '^GSPC'
# Define different groups of symbols for comparison
compare_symbols_1 = ['DX-Y.NYB', 'GC=F', 'CL=F', 'TLT', 'HG=F'] # Removed 'BTC-USD' to have exactly 5 symbols
compare_symbols_2 = ['SI=F', 'HG=F', 'CL=F', 'TLT', 'DX-Y.NYB']
compare_symbols_3 = ['^GSPC', 'DX-Y.NYB', 'CL=F', 'BTC-USD'] # This group has only 4 symbols; consider adding one more
compare_symbols_4 = ['EURUSD=X', 'JPY=X', 'GBPUSD=X', 'AUDUSD=X', 'CNY=X'] # Removed 'BTC-USD' to maintain consistency
# Grouping the comparison symbols for iteration
grouped_compare_symbols = [compare_symbols_1, compare_symbols_2, compare_symbols_3, compare_symbols_4]
# Dictionary mapping symbols to descriptions
symbol_descriptions = {
'^GSPC': 'S&P 500',
'GC=F': 'Gold',
'TLT': '20+ Yr Bond',
'DX-Y.NYB': 'Dollar Index',
'CL=F': 'Crude Oil',
'HG=F': 'Copper',
'SI=F': 'Silver',
'BTC-USD': 'Bitcoin',
'EURUSD=X': 'Euro/USD',
'JPY=X': 'Japanese Yen/USD',
'GBPUSD=X': 'Pound to USD',
'AUDUSD=X': 'AUD/USD',
'CNY=X': 'Chinese Yuan/USD',
# Add other descriptions as needed
}
# Use the current date as the end date
end_date = datetime.now()
# Download stock data - including all symbols for efficiency
all_symbols = base_symbols + compare_symbols_1 + compare_symbols_2 + compare_symbols_3 + compare_symbols_4
data = yf.download(all_symbols, start="2013-01-01", end=end_date)['Adj Close']
# Calculate daily returns
daily_returns = data.pct_change()
# Define the rolling window (in trading days, typically 252 trading days in a year)
rolling_window = 250
# For each base symbol, we will create a plot comparing it with each group of comparison symbols
for i, base in enumerate(base_symbols):
# Select the current group of comparison symbols
current_compare_symbols = grouped_compare_symbols[i]
# Calculate the rolling correlation for each pair in the current group
rolling_correlation = daily_returns[current_compare_symbols].rolling(window=rolling_window).corr(daily_returns[base])
# Create a new figure for each base symbol
fig, ax = plt.subplots(figsize=(15, 8))
# Plot the rolling correlation of each symbol in the current group with the base
for symbol in current_compare_symbols:
# Retrieve the description from the dictionary, defaulting to the symbol if not found
description = symbol_descriptions.get(symbol, symbol)
# Plot with the description as the label
ax.plot(rolling_correlation.index, rolling_correlation[symbol], label=f"{symbol_descriptions.get(base, base)}/{description}")
# Customize the plot
ax.set_title(f'1yr Rolling Correlation with {base} on 10yrs history', fontsize=16)
ax.set_ylabel('Correlation Coefficient', fontsize=14)
ax.set_xlabel('Date', fontsize=14)
ax.legend(loc='upper left', fontsize=12)
ax.grid(False)
# Add last updated date and time
last_updated = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
ax.text(0, 1.02, f'Last Updated: {last_updated}', transform=ax.transAxes, fontsize=9, va='bottom', ha='left')
# Show the plot
plt.tight_layout()
plt.savefig(f'G:/My Drive/WPS2N/correlations/1yr Rolling Correlation with {base} on 10yrs history.png')
plt.show()
Chart Gallery
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import seaborn as sns
import yfinance as yf
import datetime
import numpy as np
import time
import os
def plot_and_save(group_name, symbols, ticker_to_name):
# This is the directory where the images will be saved. Adjust path as needed.
save_dir = 'G:/My Drive/WPS2N/charts_gallery'
# Common setup for all charts (like start_date calculation) can go here.
current_date = datetime.datetime.now()
start_date = (current_date - datetime.timedelta(days=365)).strftime('%Y-%m-%d')
# Get the current date and time
now = datetime.datetime.now()
# Format the date and time as a string
now_str = now.strftime("%Y-%m-%d %H:%M")
for symbol in symbols:
try:
# Download the data
data = yf.download(symbol, start=start_date, end=current_date.strftime('%Y-%m-%d'))
# Calculate the last day's change and percentage change
last_close = data['Close'].iloc[-1]
prev_close = data['Close'].iloc[-2] # Previous close price
change = last_close - prev_close
percent_change = (change / prev_close) * 100
change_text = f"Last Change: {change:.2f} ({percent_change:.2f}%)"
close_text = f"Last Close: {last_close:.2f}"
# Combine the text pieces into one string, adding a newline in between
combined_text = f"{close_text}\n{change_text}"
# Create a new figure for each plot
fig, ax = plt.subplots(figsize=(12, 8)) # Adjust the size as needed
# Plotting the data
ax.plot(data.index, data["Close"], color="blue", label=ticker_to_name.get(symbol,symbol) )
last_price_point = data["Close"].iloc[-1]
last_date_point = data.index[-1]
# Set the title and labels. Fetch the name from the ticker_to_name dictionary.
ax.set_title(f"{ticker_to_name[symbol]} - 1 year")
ax.set_ylabel("Price")
ax.set_xlabel("Date")
ax.plot(last_date_point, last_price_point, 'ro') # This adds the red dot.
# Formatting dates
ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m'))
# You might need to adjust the coordinates to best fit your specific chart layout.
ax.text(0.5, 0.95, combined_text, fontsize=10, ha='center', transform=ax.transAxes)
# Add additional styling and information here (like last updated text)
ax.text(0.15, 0.90, f"Last updated: {now_str}", ha='left', va='center', transform=fig.transFigure, fontsize=9)
# Save the figure with a filename containing the group and the symbol
fig.savefig(os.path.join(save_dir, f"{group_name}_{symbol}_1yr.png"))
plt.show(fig)
except Exception as e:
# Handle your exception here (print error message, log, or whatever your policy is)
print(f"An error occurred: {e}")
# Define your watchlists
watchlists = {
'main_watchlist': ['ES=F', '^TNX','DX-Y.NYB', 'GC=F', 'BTC-USD', 'CL=F'],
'main_stock_exchanges': ['^GSPC','^DJI','^IXIC','^VIX', '^FTSE', '^GDAXI', '^N225', '^HSI', '000001.SS', '^STI', '^AORD'],
'main_futures' : ['ES=F','ZN=F', 'GC=F', 'SI=F','PL=F','CL=F', 'HG=F', 'NG=F', 'ZC=F', 'KE=F', 'CC=F', 'KC=F'],
'main_fx' : ['EURUSD=X', 'JPY=X', 'GBPUSD=X', 'AUDUSD=X', 'CNY=X', 'EURJPY=X','EURGBP=X' ],
'main_us_treasury -yield' : ['^IRX', '^FVX', '^TNX', '^TYX' ],
'main_crypto': ['BTC-USD', 'ETH-USD', 'ADA-USD', 'SOL-USD'],
'main_Mike_Stocks': ['AAPL', 'MSFT', 'GOOG', 'AMZN', 'TSLA', 'NVDA','META'],
}
# Ticker to name mapping (extend this dictionary to include all your symbols)
ticker_to_name = {
'ES=F' : 'S&P 500 Future',
'^GSPC' : 'S&P 500 Index',
'^DJI' : 'Dow Jones Industrial Index',
'^IXIC' : 'Nasdaq 100 Index',
'^VIX' : 'VIX Index',
"TLT" : '20 Plus Year Treasury Bond ETF',
'ZN=F' : '10 Year T-Note (USA)',
'PL=F' : 'Platinum',
'BTC-USD': 'Bitcoin',
'ETH-USD': 'Ethereum',
'ADA-USD': 'Cardano',
'SOL-USD': 'Solana',
'DX-Y.NYB': 'US Dollar Index',
'GC=F' : 'Gold',
'CL=F' : 'Crude Oil',
'^FTSE' : 'FTSE 100 Index',
'^GDAXI' : 'DAX Index',
'^N225' : 'Nikkei 225 Index',
'^HSI' : 'Hang Seng Index',
'000001.SS' : 'Shanghai Composite Index',
'^STI' : 'Straits Times Index',
'^AORD' : 'Australian Stock Exchange',
'EURUSD=X' : 'EUR/USD',
'JPY=X' : 'JPY/USD',
'GBPUSD=X' : 'GBP/USD',
'AUDUSD=X' : 'AUD/USD',
'CNY=X' : 'CNY/USD',
'EURJPY=X' : 'EUR/JPY',
'EURGBP=X' : 'EUR/GBP',
'SI=F' : 'Silver',
'HG=F' : 'Copper',
'NG=F' : 'Natural Gas',
'ZC=F' : 'Corn',
'KE=F' : 'Wheat',
'CC=F' : 'Cocoa',
'KC=F' : 'Coffee',
'^IRX' : '3 mnth Treasury yield',
'^FVX' : '5 yr Treasury yield',
'^TNX' : '10 yr Treasury yield',
'^TYX' : '30 yr Treasury yield',
'BTC-USD': 'Bitcoin',
'ETH-USD': 'Ethereum',
'ADA-USD': 'Cardano',
'SOL-USD': 'Solana',
'AAPL' : 'Apple',
'MSFT' : 'Microsoft',
'GOOG' : 'Google',
'AMZN' : 'Amazon',
'TSLA' : 'Tesla',
'BABA' : 'Alibaba',
'NVDA' : 'NVIDIA',
'META' : 'Meta',
}
# Loop through the watchlists and process each one
for group_name, symbols in watchlists.items():
plot_and_save(group_name, symbols, ticker_to_name)
def plot_and_save(group_name, symbols, ticker_to_name):
# This is the directory where the images will be saved. Adjust path as needed.
save_dir = 'G:/My Drive/WPS2N/charts_gallery'
# Common setup for all charts (like start_date calculation) can go here.
current_date = datetime.datetime.now()
start_date = (current_date - datetime.timedelta(days=365*5)).strftime('%Y-%m-%d')
# Get the current date and time
now = datetime.datetime.now()
# Format the date and time as a string
now_str = now.strftime("%Y-%m-%d %H:%M:%S")
for symbol in symbols:
try:
# Download the data
data = yf.download(symbol, start=start_date, end=current_date.strftime('%Y-%m-%d'))
# Calculate the last day's change and percentage change
last_close = data['Close'].iloc[-1]
prev_close = data['Close'].iloc[-2] # Previous close price
change = last_close - prev_close
percent_change = (change / prev_close) * 100
change_text = f"Last Change: {change:.2f} ({percent_change:.2f}%)"
close_text = f"Last Close: {last_close:.2f}"
# Combine the text pieces into one string, adding a newline in between
combined_text = f"{close_text}\n{change_text}"
# Create a new figure for each plot
fig, ax = plt.subplots(figsize=(12, 8)) # Adjust the size as needed
# Plotting the data
ax.plot(data.index, data["Close"], color="blue", label=ticker_to_name.get(symbol,symbol) )
last_price_point = data["Close"].iloc[-1]
last_date_point = data.index[-1]
# Set the title and labels. Fetch the name from the ticker_to_name dictionary.
ax.set_title(f"{ticker_to_name[symbol]} - 5 year")
ax.set_ylabel("Price")
ax.set_xlabel("Date")
ax.plot(last_date_point, last_price_point, 'ro') # This adds the red dot.
# Formatting dates
ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m'))
# You might need to adjust the coordinates to best fit your specific chart layout.
ax.text(0.5, 0.95, combined_text, fontsize=10, ha='center', transform=ax.transAxes)
# Add additional styling and information here (like last updated text)
ax.text(0.15, 0.90, f"Last updated: {now_str}", ha='left', va='center', transform=fig.transFigure, fontsize=9)
# Save the figure with a filename containing the group and the symbol
fig.savefig(os.path.join(save_dir, f"{group_name}_{symbol}_5yr.png"))
# Close the figure after saving to free up memory
plt.show(fig)
except Exception as e:
# Handle your exception here (print error message, log, or whatever your policy is)
print(f"An error occurred: {e}")
# Define your watchlists
watchlists = {
'main_watchlist': ['ES=F', '^TNX','DX-Y.NYB', 'GC=F', 'BTC-USD', 'CL=F'],
'main_stock_exchanges': ['^GSPC','^DJI','^IXIC','^VIX', '^FTSE', '^GDAXI', '^N225', '^HSI', '000001.SS', '^STI', '^AORD'],
'main_futures' : ['ES=F','ZN=F', 'GC=F', 'SI=F','PL=F','CL=F', 'HG=F', 'NG=F', 'ZC=F', 'KE=F', 'CC=F', 'KC=F'],
'main_fx' : ['EURUSD=X', 'JPY=X', 'GBPUSD=X', 'AUDUSD=X', 'CNY=X', 'EURJPY=X','EURGBP=X' ],
'main_us_treasury -yield' : ['^IRX', '^FVX', '^TNX', '^TYX' ],
'main_crypto': ['BTC-USD', 'ETH-USD', 'ADA-USD', 'SOL-USD'],
'main_Mike_Stocks': ['AAPL', 'MSFT', 'GOOG', 'AMZN', 'TSLA', 'NVDA','META'],
}
# Ticker to name mapping (extend this dictionary to include all your symbols)
ticker_to_name = {
'ES=F' : 'S&P 500 Future',
'^GSPC' : 'S&P 500 Index',
'^DJI' : 'Dow Jones Industrial Index',
'^IXIC' : 'Nasdaq 100 Index',
'^VIX' : 'VIX Index',
"TLT" : '20 Plus Year Treasury Bond ETF',
'ZN=F' : '10 Year T-Note (USA)',
'PL=F' : 'Platinum',
'BTC-USD': 'Bitcoin',
'ETH-USD': 'Ethereum',
'ADA-USD': 'Cardano',
'SOL-USD': 'Solana',
'DX-Y.NYB': 'US Dollar Index',
'GC=F' : 'Gold',
'CL=F' : 'Crude Oil',
'^FTSE' : 'FTSE 100 Index',
'^GDAXI' : 'DAX Index',
'^N225' : 'Nikkei 225 Index',
'^HSI' : 'Hang Seng Index',
'000001.SS' : 'Shanghai Composite Index',
'^STI' : 'Straits Times Index',
'^AORD' : 'Australian Stock Exchange',
'EURUSD=X' : 'EUR/USD',
'JPY=X' : 'JPY/USD',
'GBPUSD=X' : 'GBP/USD',
'AUDUSD=X' : 'AUD/USD',
'CNY=X' : 'CNY/USD',
'EURJPY=X' : 'EUR/JPY',
'EURGBP=X' : 'EUR/GBP',
'SI=F' : 'Silver',
'HG=F' : 'Copper',
'NG=F' : 'Natural Gas',
'ZC=F' : 'Corn',
'KE=F' : 'Wheat',
'CC=F' : 'Cocoa',
'KC=F' : 'Coffee',
'^IRX' : '3 mnth Treasury yield',
'^FVX' : '5 yr Treasury yield',
'^TNX' : '10 yr Treasury yield',
'^TYX' : '30 yr Treasury yield',
'BTC-USD': 'Bitcoin',
'ETH-USD': 'Ethereum',
'ADA-USD': 'Cardano',
'SOL-USD': 'Solana',
'AAPL' : 'Apple',
'MSFT' : 'Microsoft',
'GOOG' : 'Google',
'AMZN' : 'Amazon',
'TSLA' : 'Tesla',
'BABA' : 'Alibaba',
'NVDA' : 'NVIDIA',
'META' : 'Meta',
}
# Loop through the watchlists and process each one
for group_name, symbols in watchlists.items():
plot_and_save(group_name, symbols, ticker_to_name)
def plot_and_save(group_name, symbols, ticker_to_name):
# This is the directory where the images will be saved. Adjust path as needed.
save_dir = 'G:/My Drive/WPS2N/charts_gallery'
# Common setup for all charts (like start_date calculation) can go here.
current_date = datetime.datetime.now()
start_date = (current_date - datetime.timedelta(days=365*100)).strftime('%Y-%m-%d')
# Get the current date and time
now = datetime.datetime.now()
# Format the date and time as a string
now_str = now.strftime("%Y-%m-%d %H:%M:%S")
for symbol in symbols:
try:
# Download the data
data = yf.download(symbol, start=start_date, end=current_date.strftime('%Y-%m-%d'))
# Calculate the last day's change and percentage change
last_close = data['Close'].iloc[-1]
prev_close = data['Close'].iloc[-2] # Previous close price
change = last_close - prev_close
percent_change = (change / prev_close) * 100
change_text = f"Last Change: {change:.2f} ({percent_change:.2f}%)"
close_text = f"Last Close: {last_close:.2f}"
# Combine the text pieces into one string, adding a newline in between
combined_text = f"{close_text}\n{change_text}"
# Create a new figure for each plot
fig, ax = plt.subplots(figsize=(12, 8)) # Adjust the size as needed
# Plotting the data
ax.plot(data.index, data["Close"], color="blue", label=ticker_to_name.get(symbol,symbol) )
last_price_point = data["Close"].iloc[-1]
last_date_point = data.index[-1]
# Set the title and labels. Fetch the name from the ticker_to_name dictionary.
ax.set_title(f"{ticker_to_name[symbol]} - all history")
ax.set_ylabel("Price")
ax.set_xlabel("Date")
ax.plot(last_date_point, last_price_point, 'ro') # This adds the red dot.
# Formatting dates
ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m'))
# You might need to adjust the coordinates to best fit your specific chart layout.
ax.text(0.5, 0.95, combined_text, fontsize=10, ha='center', transform=ax.transAxes)
# Add additional styling and information here (like last updated text)
ax.text(0.15, 0.90, f"Last updated: {now_str}", ha='left', va='center', transform=fig.transFigure, fontsize=9)
# Save the figure with a filename containing the group and the symbol
fig.savefig(os.path.join(save_dir, f"{group_name}_{symbol}_all.png"))
# Close the figure after saving to free up memory
plt.show(fig)
except Exception as e:
# Handle your exception here (print error message, log, or whatever your policy is)
print(f"An error occurred: {e}")
# Define your watchlists
watchlists = {
'main_watchlist': ['ES=F', '^TNX','DX-Y.NYB', 'GC=F', 'BTC-USD', 'CL=F'],
'main_stock_exchanges': ['^GSPC','^DJI','^IXIC','^VIX', '^FTSE', '^GDAXI', '^N225', '^HSI', '000001.SS', '^STI', '^AORD'],
'main_futures' : ['ES=F','ZN=F', 'GC=F', 'SI=F','PL=F','CL=F', 'HG=F', 'NG=F', 'ZC=F', 'KE=F', 'CC=F', 'KC=F'],
'main_fx' : ['EURUSD=X', 'JPY=X', 'GBPUSD=X', 'AUDUSD=X', 'CNY=X', 'EURJPY=X','EURGBP=X' ],
'main_us_treasury -yield' : ['^IRX', '^FVX', '^TNX', '^TYX' ],
'main_crypto': ['BTC-USD', 'ETH-USD', 'ADA-USD', 'SOL-USD'],
'main_Mike_Stocks': ['AAPL', 'MSFT', 'GOOG', 'AMZN', 'TSLA', 'NVDA','META'],
}
# Ticker to name mapping (extend this dictionary to include all your symbols)
ticker_to_name = {
'ES=F' : 'S&P 500 Future',
'^GSPC' : 'S&P 500 Index',
'^DJI' : 'Dow Jones Industrial Index',
'^IXIC' : 'Nasdaq 100 Index',
'^VIX' : 'VIX Index',
"TLT" : '20 Plus Year Treasury Bond ETF',
'ZN=F' : '10 Year T-Note (USA)',
'PL=F' : 'Platinum',
'BTC-USD': 'Bitcoin',
'ETH-USD': 'Ethereum',
'ADA-USD': 'Cardano',
'SOL-USD': 'Solana',
'DX-Y.NYB': 'US Dollar Index',
'GC=F' : 'Gold',
'CL=F' : 'Crude Oil',
'^FTSE' : 'FTSE 100 Index',
'^GDAXI' : 'DAX Index',
'^N225' : 'Nikkei 225 Index',
'^HSI' : 'Hang Seng Index',
'000001.SS' : 'Shanghai Composite Index',
'^STI' : 'Straits Times Index',
'^AORD' : 'Australian Stock Exchange',
'EURUSD=X' : 'EUR/USD',
'JPY=X' : 'JPY/USD',
'GBPUSD=X' : 'GBP/USD',
'AUDUSD=X' : 'AUD/USD',
'CNY=X' : 'CNY/USD',
'EURJPY=X' : 'EUR/JPY',
'EURGBP=X' : 'EUR/GBP',
'SI=F' : 'Silver',
'HG=F' : 'Copper',
'NG=F' : 'Natural Gas',
'ZC=F' : 'Corn',
'KE=F' : 'Wheat',
'CC=F' : 'Cocoa',
'KC=F' : 'Coffee',
'^IRX' : '3 mnth Treasury yield',
'^FVX' : '5 yr Treasury yield',
'^TNX' : '10 yr Treasury yield',
'^TYX' : '30 yr Treasury yield',
'BTC-USD': 'Bitcoin',
'ETH-USD': 'Ethereum',
'ADA-USD': 'Cardano',
'SOL-USD': 'Solana',
'AAPL' : 'Apple',
'MSFT' : 'Microsoft',
'GOOG' : 'Google',
'AMZN' : 'Amazon',
'TSLA' : 'Tesla',
'BABA' : 'Alibaba',
'NVDA' : 'NVIDIA',
'META' : 'Meta',
}
# Loop through the watchlists and process each one
for group_name, symbols in watchlists.items():
plot_and_save(group_name, symbols, ticker_to_name)
# you will need to have a symbol_name_mapping.csv file that has all the futures symbol and descriptions.
# Define base directory for saving the plots
base_save_dir = r'G:\My Drive\WPS2N\charts_gallery\futures'
# Define end date for fetching data (currently set to today)
#start_date = (datetime.now() - pd.DateOffset(years=1)).strftime('%Y-%m-%d')
end_date = datetime.now().strftime('%Y-%m-%d')
# Load tickers and descriptions from CSV file
csv_file_path = 'G:\\My Drive\\WPS2N\\norgate\\symbol_name_mapping.csv' # Update this path to your CSV file
tickers_df = pd.read_csv(csv_file_path)
tickers = tickers_df['Symbol'].tolist()
descriptions = dict(zip(tickers_df['Symbol'], tickers_df['Name']))
# Download data and create plots
for ticker in tickers:
try:
# Download data
data = norgatedata.price_timeseries(
ticker,
timeseriesformat='pandas-dataframe',
#start_date=start_date,
end_date=end_date
)
# Replace 0 with NaN and then forward fill the last valid observation forward
data['Open Interest'] = data['Open Interest'].replace(0, np.nan).ffill()
# Calculate the 200-day SMA and RSI
data['SMA_200'] = ta.sma(data['Close'], length=200)
data['RSI'] = ta.rsi(data['Close'], length=14)
# Create subplots - RSI, main chart, Open Interest, and Z-Score
fig, (ax_rsi, ax_main, ax_oi) = plt.subplots(3, 1, sharex=True, gridspec_kw={'height_ratios': [0.5, 2.5, 0.5]}, figsize=(20,14))
# Remove the spaces between the subplots
fig.subplots_adjust(hspace=0)
# Generate a numerical range for x-axis (0, 1, 2, ..., len(data) - 1)
x = np.arange(len(data))
# Plot RSI
ax_rsi.plot(x, data['RSI'], label='RSI(14)', color='purple')
ax_rsi.axhline(30, color='r', linestyle='--')
ax_rsi.axhline(70, color='r', linestyle='--')
ax_rsi.set_ylabel('RSI')
ax_rsi.grid(False) # Turn off grid for RSI panel
ax_rsi.legend()
# Plot Open Interest
ax_oi.plot(x, data['Open Interest'], color='skyblue', linewidth=1)
ax_oi.set_ylabel('Open Interest')
ax_oi.grid(False) # Grid on for Open Interest panel
# Function to format the y-axis values
def millions_formatter(x, pos):
return '%1.2fM' % (x * 1e-6)
# Set this formatter to the y-axis of the Open Interest subplot
ax_oi.yaxis.set_major_formatter(FuncFormatter(millions_formatter))
# Plot closing prices as a simple black line
ax_main.plot(x, data['Close'], color='black', linewidth=1)
# Plot 200-day SMA on main chart
ax_main.plot(x, data['SMA_200'], label='200-day SMA', color='orange', linewidth=1.25)
ax_main.set_ylabel('Price')
ax_main.grid(False) # Turn off grid for main panel
ax_main.legend()
# Set up twin axis for Volume on main chart
ax_vol = ax_main.twinx()
ax_vol.bar(x, data['Volume'], color='gray', alpha=0.3, width=0.6)
ax_vol.set_ylabel('Volume')
ax_vol.grid(False) # Turn off grid for volume panel
ax_vol.yaxis.set_visible(False) # Hide the y-axis values (tick labels)
# Adjust the y-axis scale for the volume to occupy only the bottom 1/3 of the main chart
max_volume = data['Volume'].max()
ax_vol.set_ylim(0, max_volume * 3) # Adjust the 3 to a larger number to further shrink the volume bars
# Set background color for all subplots to white
for ax in [ax_rsi, ax_main, ax_vol]:
ax.set_facecolor('white')
# Set x-axis major ticks to show only the dates present in the data
ax_main.xaxis.set_major_locator(MaxNLocator(integer=True)) # Ensure the locator treats the tick locations as integers
# Set the x-tick locations and labels
tick_locations = ax_main.get_xticks()
ax_main.set_xticks(tick_locations) # Ensure the tick locations are fixed
# Filter the tick locations to ensure they are within the index range to avoid IndexError
valid_tick_locations = [tick for tick in tick_locations if tick >= 0 and tick < len(data.index)]
# Set the x-tick labels to correspond with the dates
ax_main.set_xticklabels([data.index[int(tick)].strftime('%Y-%m-%d') if int(tick) in valid_tick_locations else '' for tick in tick_locations], rotation=45)
# Adjust x-axis limits to remove space on the left and reduce space on the right
margin_left = 0 # No margin on the left
margin_right = 50 # Small margin on the right
ax_main.set_xlim([x[0] - margin_left, x[-1] + margin_right])
# Set main plot title to include the ticker symbol
ax_main.set_title(f"{descriptions.get(ticker, ticker)} ({ticker})")
# Add additional text to the chart
last_close = data['Close'].iloc[-1]
prev_close = data['Close'].iloc[-2]
change = last_close - prev_close
percent_change = (change / prev_close) * 100
last_date_point = data.index[-1]
combined_text = f"Last Close: {last_close:.2f} ({last_date_point.strftime('%Y-%m-%d')})\nLast Change: {change:.4f} ({percent_change:.2f}%)"
# Choose location on the plot for the text, adjust as necessary
plt.text(0.01, 0.98, combined_text, transform=ax_main.transAxes, fontsize=12,
verticalalignment='top', bbox=dict(boxstyle='round', facecolor='wheat', alpha=0.5))
plt.show()
# Save the figure
fig.savefig(os.path.join(base_save_dir, f"{ticker}.png"), bbox_inches='tight')
#plt.close(fig) # Close the plot to free memory
except Exception as e:
print(f"Error processing ticker {ticker}: {e}")
continue # Continue with the next ticker
Accordion Content
Backtesting – Backtrader
News
Tab Content
Screeners
Tab Content
Trading Strategies
Tab Content
AmiBroker
MQL 4/5
Tradingview
A world class data provider that is extremely cost effective. Most of the code on this site is powered by Norgate Data