Skip to content

Instantly share code, notes, and snippets.

@tony-lizy
Last active January 1, 2024 00:28
Show Gist options
  • Save tony-lizy/9f7f3514dbaa17408418fcb2b473e172 to your computer and use it in GitHub Desktop.
Save tony-lizy/9f7f3514dbaa17408418fcb2b473e172 to your computer and use it in GitHub Desktop.
"""
Author: chatGPT
Date: 2024-01-01
This module is designed to analyze and visualize ETF portfolio performances over different time frames.
"""
import pandas as pd
import yfinance as yf
import datetime
"""
Results for QQQ:
5 years:
Monthly Equal Investment Return: 89182
Total invested money: 59000
Total returns ratio: 1.51 times
----------------------
Annual Min Investment Return: 115892
Total invested money: 60000
Total returns ratio: 1.93 times
----------------------
Custom Monthly Investment Return Based on weight: 159858
Total invested money: 108500.0
Total returns ratio: 1.47 times
################################################
10 years:
Monthly Equal Investment Return: 294255
Total invested money: 119000
Total returns ratio: 2.47 times
----------------------
Annual Min Investment Return: 350793
Total invested money: 120000
Total returns ratio: 2.92 times
----------------------
Custom Monthly Investment Return Based on weight: 438914
Total invested money: 190700.0
Total returns ratio: 2.30 times
################################################
15 years:
Monthly Equal Investment Return: 760773
Total invested money: 179000
Total returns ratio: 4.25 times
----------------------
Annual Min Investment Return: 916124
Total invested money: 180000
Total returns ratio: 5.09 times
----------------------
Custom Monthly Investment Return Based on weight: 1014946
Total invested money: 264100.0
Total returns ratio: 3.84 times
################################################
20 years:
Monthly Equal Investment Return: 1368888
Total invested money: 239000
Total returns ratio: 5.73 times
----------------------
Annual Min Investment Return: 1655598
Total invested money: 240000
Total returns ratio: 6.90 times
----------------------
Custom Monthly Investment Return Based on weight: 2671541
Total invested money: 417000.0
Total returns ratio: 6.41 times
################################################
Results for SPY:
5 years:
Monthly Equal Investment Return: 77075
Total invested money: 59000
Total returns ratio: 1.31 times
----------------------
Annual Min Investment Return: 95436
Total invested money: 60000
Total returns ratio: 1.59 times
----------------------
Custom Monthly Investment Return Based on weight: 136789
Total invested money: 106300.0
Total returns ratio: 1.29 times
################################################
10 years:
Monthly Equal Investment Return: 205450
Total invested money: 119000
Total returns ratio: 1.73 times
----------------------
Annual Min Investment Return: 239495
Total invested money: 120000
Total returns ratio: 2.00 times
----------------------
Custom Monthly Investment Return Based on weight: 325522
Total invested money: 194600.0
Total returns ratio: 1.67 times
################################################
15 years:
Monthly Equal Investment Return: 436981
Total invested money: 179000
Total returns ratio: 2.44 times
----------------------
Annual Min Investment Return: 514855
Total invested money: 180000
Total returns ratio: 2.86 times
----------------------
Custom Monthly Investment Return Based on weight: 637724
Total invested money: 275000.0
Total returns ratio: 2.32 times
################################################
20 years:
Monthly Equal Investment Return: 664102
Total invested money: 239000
Total returns ratio: 2.78 times
----------------------
Annual Min Investment Return: 782021
Total invested money: 240000
Total returns ratio: 3.26 times
----------------------
Custom Monthly Investment Return Based on weight: 1484009
Total invested money: 474900.0
Total returns ratio: 3.12 times
################################################
"""
# Define the tickers and the amount to invest
tickers = ['QQQ', 'SPY'] # List of ETF tickers to be used in the investment simulation
monthly_investment = 1000 # Amount to be invested monthly in USD
annual_investment = 12000 # Amount to be invested annually in USD
# Define the periods to analyze
periods = [5, 10, 15, 20]
# Function to simulate the investment strategy
def simulate_investment(ticker, start_date, end_date, investment, frequency='M'):
"""
Simulate an investment strategy for a given ticker, start and end date, investment amount, and frequency.
Parameters:
ticker (str): The stock ticker symbol to simulate investment for.
start_date (datetime): The start date for the investment period.
end_date (datetime): The end date for the investment period.
investment (float): The amount of money to invest at each interval.
frequency (str): The frequency of investment ('M' for monthly, 'Y' for yearly, 'custom' for a custom strategy).
Returns:
tuple: A tuple containing the total value of the investment and the total money spent.
"""
# Get historical data for the ticker using yfinance
price_data = yf.download(ticker, start=start_date, end=end_date)
# Calculate the latest price from the available data
latest_price = price_data['Close'].iloc[-1]
investment_returns = 0
if frequency == 'M': # invest same money each month without picking time
# Get the first trading day of each month within the date range
first_trading_days = price_data.resample('MS').first().index
# Filter the dates to the investment period
investment_dates = first_trading_days[(first_trading_days >= start_date) & (first_trading_days <= end_date)]
# Backfill missing dates
price_data = price_data.reindex(investment_dates, method='bfill')
# Calculate cumulative investment returns based on the close price of the first trading day of each month
shares = (investment / price_data['Close']).cumsum()
money_spent = len(shares) * investment
elif frequency == 'Y': # invest same money each year, picking the min price of that year
# Find the lowest close price of each year
yearly_low = price_data.resample('Y')['Close'].min()
# Get the dates when the lowest close price occurred
investment_dates = yearly_low.index
shares = (investment / yearly_low).cumsum()
money_spent = len(shares) * investment
elif frequency == 'custom': # invest same money each month, invest more or less based on if the price is below the moving average
# Get historical data for the ticker using yfinance
price_data['MA10'] = price_data['Close'].rolling(window=10).mean()
price_data['MA20'] = price_data['Close'].rolling(window=20).mean()
price_data['MA50'] = price_data['Close'].rolling(window=50).mean()
price_data['MA100'] = price_data['Close'].rolling(window=100).mean()
price_data['MA250'] = price_data['Close'].rolling(window=250).mean()
price_data['MA500'] = price_data['Close'].rolling(window=500).mean()
price_data['MA1000'] = price_data['Close'].rolling(window=1000).mean()
multipliers = {
'MA1000': 5, # 5 times of investment if the price is below MA1000
'MA500': 4,
'MA250': 3,
'MA100': 2,
'MA50': 1.5,
'MA20': 1.2,
'MA10': 1,
'otherwise': 0.8
}
# Get the first trading day of each month within the date range
first_trading_days = price_data.resample('MS').first().index
# Filter the dates to the investment period
investment_dates = first_trading_days[(first_trading_days >= start_date) & (first_trading_days <= end_date)]
# Backfill missing dates
price_data = price_data.reindex(investment_dates, method='bfill')
# Calculate the investment multiplier based on the MA conditions
investment_multipliers = price_data.apply(lambda row: (
multipliers['MA1000'] if row['Close'] < row['MA1000'] else
multipliers['MA500'] if row['Close'] < row['MA500'] else
multipliers['MA250'] if row['Close'] < row['MA250'] else
multipliers['MA100'] if row['Close'] < row['MA100'] else
multipliers['MA50'] if row['Close'] < row['MA50'] else
multipliers['MA20'] if row['Close'] < row['MA20'] else
multipliers['MA10'] if row['Close'] < row['MA10'] else
multipliers['otherwise']), axis=1)
adjusted_investment = investment * investment_multipliers
shares = (adjusted_investment / price_data['Close']).cumsum()
money_spent = adjusted_investment.sum()
return round(latest_price * shares.iloc[-1]), money_spent
# Function to compare the two investment strategies
def compare_investment_strategies(tickers, periods, monthly_investment, annual_investment):
"""
Compares the performance of different investment strategies over a range of periods for a given set of tickers.
Parameters:
tickers (list): List of ticker symbols to analyze.
periods (list): List of periods (in years) over which to simulate the investment strategies.
monthly_investment (float): The amount to be invested monthly.
annual_investment (float): The amount to be invested annually at the lowest price each year.
Returns:
dict: A dictionary containing the simulation results for each ticker and period.
"""
results = {}
current_date = datetime.datetime.now()
for ticker in tickers:
results[ticker] = {}
for period in periods:
start_date = current_date - pd.DateOffset(years=period)
end_date = current_date
# Simulate monthly investment
monthly_returns, monthly_money_spent = simulate_investment(ticker, start_date, end_date, monthly_investment,
frequency='M')
# Simulate annual investment at the lowest price each year
annual_returns, annual_money_spent = simulate_investment(ticker, start_date, end_date, annual_investment,
frequency='Y')
# Simulate custom monthly investment
custom_monthly_returns, custom_monthly_money_spent = simulate_investment(ticker, start_date, end_date,
monthly_investment,
frequency='custom')
results[ticker][period] = {
'total_monthly_investment': monthly_money_spent,
'total_annual_investment': annual_money_spent,
'monthly': monthly_returns,
'annual': annual_returns,
'custom_monthly': custom_monthly_returns,
'custom_monthly_investment': custom_monthly_money_spent
}
return results
def _main():
"""
This function runs the investment strategy comparison and prints out the results.
"""
investment_results = compare_investment_strategies(tickers, periods, monthly_investment, annual_investment)
for ticker in investment_results:
print(f"Results for {ticker}:")
for period in investment_results[ticker]:
print(f"{period} years:")
print(f" Monthly Equal Investment Return: {investment_results[ticker][period]['monthly']}")
print(f" Total invested money: {investment_results[ticker][period]['total_monthly_investment']}")
print(
f" Total returns ratio: {investment_results[ticker][period]['monthly'] / investment_results[ticker][period]['total_monthly_investment']:.2f} times")
print("----------------------")
print(f" Annual Min Investment Return: {investment_results[ticker][period]['annual']}")
print(f" Total invested money: {investment_results[ticker][period]['total_annual_investment']}")
print(
f" Total returns ratio: {investment_results[ticker][period]['annual'] / investment_results[ticker][period]['total_annual_investment']:.2f} times")
print("----------------------")
print(f" Custom Monthly Investment Return Based on weight: {investment_results[ticker][period]['custom_monthly']}")
print(
f" Total invested money: {investment_results[ticker][period]['custom_monthly_investment']}")
print(
f" Total returns ratio: {investment_results[ticker][period]['custom_monthly'] / investment_results[ticker][period]['custom_monthly_investment']:.2f} times")
print("################################################")
if __name__ == '__main__':
_main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment