Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .Jules/palette.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
**Learning:** Adding color-coded indicators (Green/Red) and emojis (💰, 📉) in CLI tools significantly reduces cognitive load when parsing financial data streams. It transforms a wall of text into a scannable narrative.
**Action:** For data-heavy CLI applications, always implement a semantic color system and visual anchors (icons/emojis) for key events.

## 2024-05-23 - CLI Accessibility and Configuration
**Learning:** Hardcoded simulation parameters create friction and limit accessibility. Adding CLI arguments (`argparse`) empowers users to explore scenarios without code edits. Additionally, providing a `--no-color` flag is crucial for users with visual impairments or those piping output to logs.
**Action:** Always implement standard CLI flags for configuration and accessibility (quiet mode, no-color) in command-line tools.
## 2024-05-23 - CLI Accessibility and Control
**Learning:** While color and emojis enhance UX, they can be inaccessible (color blindness) or intrusive (automation logs). Providing `--no-color` and `--quiet` flags is essential for a robust CLI tool that respects user context and accessibility needs.
**Action:** Always include flags to disable visual enhancements and suppress verbose output in CLI tools.
101 changes: 101 additions & 0 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL Advanced"

on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
schedule:
- cron: '42 16 * * 6'

jobs:
analyze:
name: Analyze (${{ matrix.language }})
# Runner size impacts CodeQL analysis time. To learn more, please see:
# - https://gh.io/recommended-hardware-resources-for-running-codeql
# - https://gh.io/supported-runners-and-hardware-resources
# - https://gh.io/using-larger-runners (GitHub.com only)
# Consider using larger runners or machines with greater resources for possible analysis time improvements.
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
permissions:
# required for all workflows
security-events: write

# required to fetch internal or private CodeQL packs
packages: read

# only required for workflows in private repositories
actions: read
contents: read

strategy:
fail-fast: false
matrix:
include:
- language: actions
build-mode: none
- language: python
build-mode: none
# CodeQL supports the following values keywords for 'language': 'actions', 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'rust', 'swift'
# Use `c-cpp` to analyze code written in C, C++ or both
# Use 'java-kotlin' to analyze code written in Java, Kotlin or both
# Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
# To learn more about changing the languages that are analyzed or customizing the build mode for your analysis,
# see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning.
# If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
steps:
- name: Checkout repository
uses: actions/checkout@v4

# Add any setup steps before running the `github/codeql-action/init` action.
# This includes steps like installing compilers or runtimes (`actions/setup-node`
# or others). This is typically only required for manual builds.
# - name: Setup runtime (example)
# uses: actions/setup-example@v1

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v4
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.

# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality

# If the analyze step fails for one of the languages you are analyzing with
# "We were unable to automatically build your code", modify the matrix above
# to set the build mode to "manual" for that language. Then modify this step
# to build your code.
# ℹ️ Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
- name: Run manual build steps
if: matrix.build-mode == 'manual'
shell: bash
run: |
echo 'If you are using a "manual" build mode for one or more of the' \
'languages you are analyzing, replace this with the commands to build' \
'your code, for example:'
echo ' make bootstrap'
echo ' make release'
exit 1

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v4
with:
category: "/language:${{matrix.language}}"
3 changes: 1 addition & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,4 @@

# Python
__pycache__/
*.py[cod]
*$py.class
*.pyc
31 changes: 26 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ A Python-based CLI tool that simulates Bitcoin trading using a 'Golden Cross' mo

## Features

- **Price Simulation:** Uses Geometric Brownian Motion to simulate 60 days of Bitcoin prices.
- **Price Simulation:** Uses Geometric Brownian Motion to simulate Bitcoin prices.
- **Trading Strategy:** Implements a Golden Cross strategy (Short MA > Long MA = Buy, Short MA < Long MA = Sell).
- **Rich CLI Output:** features color-coded logs (Green for Buy/Profit, Red for Sell/Loss) and emojis for better readability.
- **Rich CLI Output:** Features color-coded logs (Green for Buy/Profit, Red for Sell/Loss) and emojis for better readability.
- **Performance metrics:** Compares the strategy's performance against a "Buy and Hold" approach.
- **Customizable:** Configure simulation parameters via command-line arguments.

## Installation

Expand All @@ -20,16 +21,36 @@ pip install -r requirements.txt

## Usage

Run the simulation script:
Run the simulation script with default settings (60 days, $10k initial cash):

```bash
python bitcoin_trading_simulation.py
```

### Options

Customize the simulation with the following arguments:

```bash
python bitcoin_trading_simulation.py --days 100 --initial-cash 5000 --initial-price 60000 --volatility 0.03
```

- `--days`: Number of days to simulate (default: 60)
- `--initial-cash`: Initial cash amount (default: 10000)
- `--initial-price`: Initial Bitcoin price (default: 50000)
- `--volatility`: Price volatility (default: 0.02)
- `--quiet`: Suppress daily portfolio log (only show final result)
- `--no-color`: Disable colored output (for accessibility or logging)

Example:
```bash
python bitcoin_trading_simulation.py --days 30 --quiet --no-color
```

## Tests

Run the test suite:
Run the test suite using `pytest`:

```bash
python test.py
pytest
```
Binary file not shown.
Binary file added __pycache__/test_bitcoin_trading.cpython-312.pyc
Binary file not shown.
51 changes: 36 additions & 15 deletions bitcoin_trading_simulation.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import argparse
import numpy as np
import pandas as pd
import argparse


class Colors:
HEADER = '\033[95m'
Expand All @@ -19,6 +21,7 @@ def disable(cls):
cls.ENDC = ''
cls.BOLD = ''


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.
Expand All @@ -33,6 +36,7 @@ def simulate_bitcoin_prices(days=60, initial_price=50000, volatility=0.02):
prices.append(prices[-1] + price_change)
return pd.Series(prices, name='Price')


def calculate_moving_averages(prices, short_window=7, long_window=30):
"""
Calculates short and long moving averages for a given price series.
Expand All @@ -43,6 +47,7 @@ def calculate_moving_averages(prices, short_window=7, long_window=30):
signals['long_mavg'] = prices.rolling(window=long_window, min_periods=1, center=False).mean()
return signals


def generate_trading_signals(signals):
"""
Generates trading signals based on the Golden Cross strategy.
Expand All @@ -54,11 +59,12 @@ def generate_trading_signals(signals):
signals.loc[signals['short_mavg'] > signals['long_mavg'], 'signal'] = 1.0
# A Death Cross (sell signal)
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
signals['positions'] = signals['signal'].diff().shift(1)
return signals


def simulate_trading(signals, initial_cash=10000, quiet=False):
"""
Simulates trading based on signals and prints a daily ledger.
Expand All @@ -71,6 +77,7 @@ def simulate_trading(signals, initial_cash=10000, quiet=False):

if not quiet:
print(f"{Colors.HEADER}{Colors.BOLD}------ Daily Trading Ledger ------{Colors.ENDC}")

for i, row in signals.iterrows():
if i > 0:
portfolio.loc[i, 'cash'] = portfolio.loc[i-1, 'cash']
Expand All @@ -94,37 +101,51 @@ def simulate_trading(signals, initial_cash=10000, quiet=False):
portfolio.loc[i, 'btc'] = 0

portfolio.loc[i, 'total_value'] = portfolio.loc[i, 'cash'] + portfolio.loc[i, 'btc'] * row['price']

if not quiet:
print(f"Day {i}: Portfolio Value: ${portfolio.loc[i, 'total_value']:.2f}, Cash: ${portfolio.loc[i, 'cash']:.2f}, BTC: {portfolio.loc[i, 'btc']:.4f}")

print(f"Day {i}: Portfolio Value: ${portfolio.loc[i, 'total_value']:.2f}, "
f"Cash: ${portfolio.loc[i, 'cash']:.2f}, BTC: {portfolio.loc[i, 'btc']:.4f}")

return portfolio

def main(days, initial_price, volatility, initial_cash, quiet, no_color):
if no_color:

if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Bitcoin Trading Simulation")
parser.add_argument("--days", type=int, default=60, help="Number of days to simulate")
parser.add_argument("--initial-cash", type=float, default=10000, help="Initial cash amount")
parser.add_argument("--initial-price", type=float, default=50000, help="Initial Bitcoin price")
parser.add_argument("--volatility", type=float, default=0.02, help="Price volatility")
parser.add_argument("--quiet", action="store_true", help="Suppress daily portfolio log")
parser.add_argument("--no-color", action="store_true", help="Disable colored output")

args = parser.parse_args()

if args.no_color:
Colors.disable()

# Simulate prices
prices = simulate_bitcoin_prices(days=days, initial_price=initial_price, volatility=volatility)
prices = simulate_bitcoin_prices(days=args.days, initial_price=args.initial_price, volatility=args.volatility)

# Calculate moving averages
signals = calculate_moving_averages(prices)

# Generate trading signals
signals = generate_trading_signals(signals)

# Simulate trading
portfolio = simulate_trading(signals, initial_cash=initial_cash, quiet=quiet)
portfolio = simulate_trading(signals, initial_cash=args.initial_cash, quiet=args.quiet)

# Final portfolio performance
final_value = portfolio['total_value'].iloc[-1]
initial_cash = args.initial_cash
profit = final_value - initial_cash

# Compare with buy and hold strategy
buy_and_hold_btc = initial_cash / prices.iloc[0]
buy_and_hold_btc = args.initial_cash / prices.iloc[0]
buy_and_hold_value = buy_and_hold_btc * prices.iloc[-1]

print(f"\n{Colors.HEADER}{Colors.BOLD}------ Final Portfolio Performance ------{Colors.ENDC}")
print(f"Initial Cash: ${initial_cash:.2f}")
print(f"Initial Cash: ${args.initial_cash:.2f}")
print(f"Final Portfolio Value: ${final_value:.2f}")

if profit >= 0:
Expand Down
3 changes: 0 additions & 3 deletions test.py

This file was deleted.

Loading
Loading