Last active
October 31, 2024 15:03
-
-
Save kodejuice/fd60a1995d073056667a020faf082436 to your computer and use it in GitHub Desktop.
I use this script to know the amount of stocks i need to buy given a certain amount
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
{ | |
"NGN": [ | |
{ | |
"weight": 50, | |
"tickers": [ | |
"UCAP", | |
"TRANSCOHOT", | |
"MANSARD", | |
"BUAFOODS", | |
"PRESCO", | |
"SEPLAT", | |
"AIRTELAFRI", | |
"FIDELIT" | |
] | |
}, | |
{ | |
"weight": 30, | |
"tickers": [ | |
"STANBIC_ETF_40", | |
"JBERGER", | |
"VETIVA_ETF", | |
"FLOURMILL", | |
"BUACEMENT", | |
"FBNH", | |
"UBA", | |
"DANGSUGAR", | |
"DANGCEM" | |
] | |
}, | |
{ | |
"weight": 17, | |
"tickers": [ | |
"NASCON", | |
"ZENITHBANK", | |
"CADBURY", | |
"OANDO", | |
"MTNN", | |
"SFSREIT", | |
"UPDC", | |
"NGXGROUP" | |
] | |
}, | |
{ | |
"weight": 3, | |
"tickers": ["NESTLE", "UNILEVER", "HONYFLOUR"] | |
} | |
], | |
"CHN": [ | |
{ | |
"weight": 65, | |
"tickers": ["DQ.", "TCOM.", "PDD.", "NIO"] | |
}, | |
{ | |
"weight": 20, | |
"tickers": ["BABA.", "BIDU."] | |
}, | |
{ | |
"weight": 15, | |
"tickers": ["CNYA.", "GXC.", "CQQQ."] | |
} | |
], | |
"IND": [ | |
{ | |
"weight": 55, | |
"tickers": ["IBN.", "INDY.", "INCO", "EPI."] | |
}, | |
{ | |
"weight": 45, | |
"tickers": ["INDA.", "INFY.", "IFN", "HDB.", "PIN"] | |
} | |
], | |
"CRYPTO": [ | |
{ | |
"weight": 70, | |
"tickers": ["SHIB", "MANA"] | |
}, | |
{ | |
"weight": 30, | |
"tickers": ["LTC", "SAND", "BTC"] | |
} | |
], | |
"JPN": [ | |
{ | |
"weight": 100, | |
"tickers": ["DBJP", "DXJ", "SONY"] | |
} | |
], | |
"Misc": [ | |
{ | |
"weight": 60, | |
"tickers": [ | |
"XLK.", | |
"PTNQ", | |
"NVDA.", | |
"MSFT.", | |
"AMZN.", | |
"ARM", | |
"KSA", | |
"BINC.", | |
"BLK." | |
] | |
}, | |
{ | |
"weight": 40, | |
"tickers": ["PANW", "XLV", "VEU", "VSS", "SPDW", "AAPL", "QQQ"] | |
} | |
] | |
} |
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
# I use this script to know the amount of stocks i need to buy given a certain amount | |
# I have weighted all the stocks listed here | |
# The stocks listed are mostly Nigeria, China, Japan, India stocks plus some other stocks in US | |
# Author: Sochima Biereagu (@kodejuice), 2023 | |
# Last updated: October 2024 | |
""" | |
Usage: | |
python weighted_stocks.py [amt] [...categories] | |
_ | |
categories is any combination of 'NGN', 'JPN', 'CHN', 'IND', 'CRYPTO', 'Misc' | |
""" | |
import sys | |
import json | |
import os | |
def load_assets(json_file): | |
""" | |
Load assets from a JSON file. | |
""" | |
if not os.path.exists(json_file): | |
print(f"Error: '{json_file}' file not found.") | |
sys.exit(1) | |
try: | |
with open(json_file, 'r') as f: | |
assets = json.load(f) | |
# Validate that weights sum to 100 for each category | |
for category, groups in assets.items(): | |
total_weight = sum(group['weight'] for group in groups) | |
if total_weight != 100: | |
print(f"Error: Weights for category '{category}' sum to {total_weight}, expected 100.") | |
sys.exit(1) | |
return assets | |
except json.JSONDecodeError as e: | |
print(f"Error parsing JSON file: {e}") | |
sys.exit(1) | |
def get_amount_currency(amount): | |
""" | |
Extract the numeric amount and currency symbol from the input. | |
""" | |
amount = amount.strip() | |
if len(amount) == 0: | |
return 0, "#" | |
first_char = amount[0] | |
if first_char.isdigit() or first_char == '.': | |
# No currency symbol | |
return float(amount.replace(',', '')), "#" | |
else: | |
# Assume the first character is the currency symbol | |
try: | |
return float(amount[1:].replace(',', '')), first_char | |
except ValueError: | |
print("Error: Invalid amount format.") | |
sys.exit(1) | |
def apply_weights_given_amt(amount, category, currency_symbol, assets): | |
""" | |
Calculate the amount allocated to each ticker in a category based on weights. | |
""" | |
if category not in assets: | |
return [] | |
allocations = [] | |
for group in assets[category]: | |
weight = group['weight'] | |
tickers = group['tickers'] | |
if not tickers: | |
continue # Skip if no tickers in the group | |
amt = round((weight / 100) * amount, 2) | |
individual_amt = round(amt / len(tickers), 2) | |
for ticker in tickers: | |
allocations.append(f"{ticker} {currency_symbol}{individual_amt:,}") | |
return allocations | |
def main(amount, categories, assets): | |
""" | |
Main function to calculate and display stock allocations. | |
""" | |
amt, currency_symbol = get_amount_currency(amount) | |
if amt <= 0: | |
print("Error: Please enter a valid positive amount.") | |
sys.exit(1) | |
if not categories: | |
selected_categories = list(assets.keys()) | |
else: | |
selected_categories = [c.strip() for c in categories.split(",") if c.strip()] | |
if not selected_categories: | |
print("Error: No valid categories selected.") | |
sys.exit(1) | |
# Validate selected categories | |
invalid_categories = [c for c in selected_categories if c not in assets] | |
if invalid_categories: | |
print(f"Error: Invalid categories selected: {', '.join(invalid_categories)}") | |
sys.exit(1) | |
categories_count = len(selected_categories) | |
amount_for_each_category = round(amt / categories_count, 2) | |
results = [] | |
for category in selected_categories: | |
allocations = apply_weights_given_amt(amount_for_each_category, category, currency_symbol, assets) | |
if allocations: | |
category_header = f"{category} Allocation:" | |
results.append(category_header) | |
results.extend(allocations) | |
results.append("") # Add an empty line for separation | |
# Display the results | |
print("\n".join(results)) | |
if __name__ == '__main__': | |
args = sys.argv | |
if len(args) < 2: | |
print(__doc__) | |
sys.exit(1) | |
input_amount = args[1] | |
input_categories = ','.join(args[2:]) if len(args) > 2 else None | |
# Load assets from assets.json | |
assets = load_assets('assets.json') | |
main(input_amount, input_categories, assets) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
web port: stocks-div.vercel.app