diff --git a/.Jules/palette.md b/.Jules/palette.md new file mode 100644 index 0000000..1701edc --- /dev/null +++ b/.Jules/palette.md @@ -0,0 +1,5 @@ +# Palette's Journal + +## 2024-05-22 - Initial Setup +**Learning:** This is a CLI-based Python application, not a web app. UX principles apply to text interfaces too (readability, feedback, scannability). +**Action:** Focus on ANSI colors, spacing, and emojis to improve the CLI experience. diff --git a/bitcoin_trading_simulation.py b/bitcoin_trading_simulation.py index e619723..f000f63 100644 --- a/bitcoin_trading_simulation.py +++ b/bitcoin_trading_simulation.py @@ -1,6 +1,14 @@ import numpy as np import pandas as pd +class Colors: + HEADER = '\033[95m' + BLUE = '\033[94m' + GREEN = '\033[92m' + RED = '\033[91m' + ENDC = '\033[0m' + BOLD = '\033[1m' + def simulate_bitcoin_prices(days=60, initial_price=50000, volatility=0.02): """ Simulates Bitcoin prices for a given number of days using Geometric Brownian Motion. @@ -38,6 +46,7 @@ def generate_trading_signals(signals): signals.loc[signals['short_mavg'] < signals['long_mavg'], 'signal'] = -1.0 # We create 'positions' to represent the trading action: 1 for buy, -1 for sell, 0 for hold + # Using shift(1) to avoid lookahead bias (executing on the next day's open/close) signals['positions'] = signals['signal'].diff().shift(1) return signals @@ -45,13 +54,14 @@ def simulate_trading(signals, initial_cash=10000): """ Simulates trading based on signals and prints a daily ledger. """ + # Explicitly casting to float to avoid FutureWarning portfolio = pd.DataFrame(index=signals.index).fillna(0.0) portfolio['price'] = signals['price'] - portfolio['cash'] = initial_cash + portfolio['cash'] = float(initial_cash) portfolio['btc'] = 0.0 - portfolio['total_value'] = portfolio['cash'] + portfolio['total_value'] = float(initial_cash) - print("------ Daily Trading Ledger ------") + print(f"{Colors.HEADER}------ 📒 Daily Trading Ledger ------{Colors.ENDC}") for i, row in signals.iterrows(): if i > 0: portfolio.loc[i, 'cash'] = portfolio.loc[i-1, 'cash'] @@ -62,17 +72,20 @@ def simulate_trading(signals, initial_cash=10000): btc_to_buy = portfolio.loc[i, 'cash'] / row['price'] portfolio.loc[i, 'btc'] += btc_to_buy portfolio.loc[i, 'cash'] -= btc_to_buy * row['price'] - print(f"Day {i}: Buy {btc_to_buy:.4f} BTC at ${row['price']:.2f}") + print(f"{Colors.GREEN}Day {i}: 🟢 BUY {btc_to_buy:.4f} BTC at ${row['price']:.2f}{Colors.ENDC}") # Sell signal elif row['positions'] == -2.0: if portfolio.loc[i, 'btc'] > 0: cash_received = portfolio.loc[i, 'btc'] * row['price'] portfolio.loc[i, 'cash'] += cash_received - print(f"Day {i}: Sell {portfolio.loc[i, 'btc']:.4f} BTC at ${row['price']:.2f}") + print(f"{Colors.RED}Day {i}: 🔴 SELL {portfolio.loc[i, 'btc']:.4f} BTC at ${row['price']:.2f}{Colors.ENDC}") portfolio.loc[i, 'btc'] = 0 portfolio.loc[i, 'total_value'] = portfolio.loc[i, 'cash'] + portfolio.loc[i, 'btc'] * row['price'] + # Simplify daily output to only show action or summary periodically if we wanted, + # but for now, we'll keep the daily log but maybe make it less intrusive or just plain? + # Let's keep it as is but formatted. print(f"Day {i}: Portfolio Value: ${portfolio.loc[i, 'total_value']:.2f}, Cash: ${portfolio.loc[i, 'cash']:.2f}, BTC: {portfolio.loc[i, 'btc']:.4f}") return portfolio @@ -99,9 +112,14 @@ def simulate_trading(signals, initial_cash=10000): buy_and_hold_btc = initial_cash / prices.iloc[0] buy_and_hold_value = buy_and_hold_btc * prices.iloc[-1] - print("\n------ Final Portfolio Performance ------") + print(f"\n{Colors.HEADER}------ 📊 Final Portfolio Performance ------{Colors.ENDC}") print(f"Initial Cash: ${initial_cash:.2f}") print(f"Final Portfolio Value: ${final_value:.2f}") - print(f"Profit/Loss: ${profit:.2f}") + + if profit >= 0: + print(f"Profit/Loss: {Colors.GREEN}💰 ${profit:.2f}{Colors.ENDC}") + else: + print(f"Profit/Loss: {Colors.RED}🔻 ${profit:.2f}{Colors.ENDC}") + print(f"Buy and Hold Strategy Value: ${buy_and_hold_value:.2f}") - print("-----------------------------------------") + print(f"{Colors.HEADER}-----------------------------------------{Colors.ENDC}") diff --git a/test.py b/test.py index b326d87..6da3e34 100644 --- a/test.py +++ b/test.py @@ -1,3 +1,19 @@ -# Filename: tests/test_sample.py -def test_example(): - assert 1 + 1 == 2 +import unittest +from bitcoin_trading_simulation import simulate_bitcoin_prices, calculate_moving_averages, generate_trading_signals, simulate_trading + +class TestSimulation(unittest.TestCase): + def test_simulation_pipeline(self): + # Run the full pipeline with a smaller dataset to ensure no crashes + try: + prices = simulate_bitcoin_prices(days=20) + signals = calculate_moving_averages(prices, short_window=3, long_window=10) + signals = generate_trading_signals(signals) + portfolio = simulate_trading(signals) + + self.assertFalse(portfolio.empty) + self.assertTrue('total_value' in portfolio.columns) + except Exception as e: + self.fail(f"Simulation failed with exception: {e}") + +if __name__ == '__main__': + unittest.main()