-
-
Save tony-lizy/9f7f3514dbaa17408418fcb2b473e172 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
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