Skip to content

Instantly share code, notes, and snippets.

@kodejuice
Last active October 31, 2024 15:03
Show Gist options
  • Save kodejuice/fd60a1995d073056667a020faf082436 to your computer and use it in GitHub Desktop.
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
{
"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"]
}
]
}
# 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)
@kodejuice
Copy link
Author

kodejuice commented Oct 31, 2024

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment