This course requires 10,000 $FAT or 10,000 $AMBR.
Return to the AI & Tech Lab to gain access.
Forge Your Path to Algorithmic Trading Mastery
# In your terminal, wield these commands:
wget https://repo.anaconda.com/archive/Anaconda3-latest-Linux-x86_64.sh
bash Anaconda3-latest-Linux-x86_64.sh
# Follow the prompts, then:
source ~/.bashrc # Or ~/.zshrc if you're a rebel
conda list. If you see packages, your installation is successful!
jupyter notebook
http://localhost:8888In your new notebook, execute this spell to test your powers:
print("By the power of Python, I shall conquer the markets!")
By the power of Python, I shall conquer the markets!
In your Jupyter Notebook, execute these rituals one at a time:
!pip install pandas
The Data Hammer of the Gods
!pip install numpy
The Mathematical Axe
!pip install matplotlib seaborn
The Visualization Crystal Ball
!pip install scikit-learn
The Machine Learning Grimoire
!pip install backtrader
The Backtesting Battle Simulator
!pip install yfinance
The Market Data Scrolls
Prove your tools are ready with this verification spell:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import yfinance as yf
import backtrader as bt
print("🛡️ ALL LIBRARIES LOADED! YOU ARE NOW A FINANCIAL SORCERER. 🛡️")
!pip install <package>
Summon real financial data to prove your setup works:
# Download Apple's stock data
data = yf.download("AAPL", start="2020-01-01", end="2023-01-01")
# Display the first 5 rows
print(data.head())
Modify the spell to fetch Tesla (TSLA) data instead. What was the highest price in 2022?
tsla_data = yf.download("TSLA", start="2022-01-01", end="2023-01-01")
print(f"Highest price: {tsla_data['High'].max():.2f}")
"Hark, brave seeker of algorithmic fortunes! The stars align as Python's serpent slithers through the halls of Wall Street's ancient keep..."
Final Warning:
"Many shall attempt this journey, but only those who master both code and capital shall drink from the chalice of algorithmic abundance"
In the dark ages, financial warriors were enslaved by Excel—a beast with a thousand heads (#REF!, #VALUE!, circular references). Then came Python, the serpent of pure logic, to liberate the masses.
The Pandas library is your first true weapon. With it, you can:
# Load stock data from CSV like a wizard
import pandas as pd
data = pd.read_csv("stock_data.csv")
# Slice time periods with ease
q4_2022 = data[(data['Date'] >= '2022-10-01') &
(data['Date'] <= '2022-12-31')]
# Calculate daily returns
data['Return'] = data['Close'].pct_change()
pd.read_csv()import pandas as pd
data = pd.read_csv("sp500_jan2022.csv")
jan3 = data[data['Date'] == '2022-01-03']
top_stock = jan3.sort_values('Volume', ascending=False).iloc[0]
print(f"Highest volume: {top_stock['Symbol']} at {top_stock['Volume']:,.0f} shares")
Like Odysseus navigating between Scylla and Charybdis, you must steer through:
.dropna() - Vanishes missing values.drop_duplicates() - Banishes duplicates.clip() - Tames wild outliersWield these three mighty techniques:
import pandas as pd
# 1. Time Series Sorcery
data['Date'] = pd.to_datetime(data['Date']) # Convert to datetime
data.set_index('Date', inplace=True) # Set as index
# 2. The Rolling Thunder (Moving Calculations)
data['30D_MA'] = data['Close'].rolling(30).mean()
data['30D_Volatility'] = data['Return'].rolling(30).std()
# 3. The Resampling Phoenix (Changing Time Frames)
weekly_data = data.resample('W').last() # Weekly closing prices
Download this messy stock data and:
import pandas as pd
# Load data
data = pd.read_csv("messy_stocks.csv")
# Cleanse
clean_data = data.dropna()
clean_data['Date'] = pd.to_datetime(clean_data['Date'])
clean_data.set_index('Date', inplace=True)
# Calculate
clean_data['20D_Vol'] = clean_data['Close'].pct_change().rolling(20).std()
print(clean_data.head())
"Rising ever higher on hopes untold,
Each peak a story of fortunes bold,
But beware the turn when the music fades,
For the bull makes graves when the bear invades."
"When blood runs red in the trading pits,
And margin calls slay weaker wits,
There in the shadows we take our share,
For the bear feasts well on the bull's despair."
Wisdom of the Ancients: "The market's song is never-ending, but the melody changes with each generation. He who learns the rhythm shall dance longest."
Financial visualization is the oracle's tongue—learn to speak it fluently:
Trend analysis over time
Volume and comparisons
Price action patterns
Transform raw numbers into golden insights:
import matplotlib.pyplot as plt
import mplfinance as mpf
# Professional candlestick chart
mpf.plot(data.tail(90), # Last 90 days
type='candle',
style='charles',
title='AAPL - Candlestick Chart',
ylabel='Price ($)',
volume=True,
mav=(20,50)) # 20 & 50 day moving averages
# Custom line chart
fig, ax = plt.subplots(figsize=(12,6))
ax.plot(data['Close'], label='Price', color='gold')
ax.plot(data['30D_MA'], label='30D MA', color='red')
ax.set_title('Price with Moving Average', fontsize=16)
ax.legend()
plt.show()
import yfinance as yf
import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec
# Get data
tsla = yf.download("TSLA", start="2022-01-01", end="2023-01-01")
# Calculate RSI
delta = tsla['Close'].diff()
gain = delta.where(delta > 0, 0)
loss = -delta.where(delta < 0, 0)
avg_gain = gain.rolling(14).mean()
avg_loss = loss.rolling(14).mean()
rs = avg_gain / avg_loss
tsla['RSI'] = 100 - (100 / (1 + rs))
# Create figure
fig = plt.figure(figsize=(14,10))
gs = GridSpec(2, 1, height_ratios=[3,1])
# Price chart
ax1 = fig.add_subplot(gs[0])
ax1.plot(tsla['Close'], label='Price', color='black')
ax1.plot(tsla['Close'].rolling(10).mean(), label='10D MA', color='blue')
ax1.plot(tsla['Close'].rolling(30).mean(), label='30D MA', color='red')
ax1.set_title('TSLA 2022 - Price with Moving Averages')
ax1.legend()
# RSI chart
ax2 = fig.add_subplot(gs[1], sharex=ax1)
ax2.plot(tsla['RSI'], color='purple')
ax2.axhline(70, color='red', linestyle='--')
ax2.axhline(30, color='green', linestyle='--')
ax2.set_title('RSI (14)')
plt.tight_layout()
plt.show()
The gods of finance judge strategies by:
Reward per unit of risk
(Return - Risk-Free) / Volatility
Downside risk focus
(Return - RF) / Downside Vol
Worst peak-to-trough
(Peak - Trough) / Peak
Implement the gods' measures in code:
import numpy as np
def sharpe_ratio(returns, risk_free=0.0, periods=252):
excess_returns = returns - risk_free
return np.sqrt(periods) * excess_returns.mean() / excess_returns.std()
def max_drawdown(returns):
cumulative = (1 + returns).cumprod()
peak = cumulative.expanding().max()
drawdown = (peak - cumulative) / peak
return drawdown.max()
# Example usage
daily_returns = data['Close'].pct_change().dropna()
print(f"Sharpe Ratio: {sharpe_ratio(daily_returns):.2f}")
print(f"Max Drawdown: {max_drawdown(daily_returns):.2%}")
Given these annualized metrics:
| Strategy | Return | Volatility | Max DD |
|---|---|---|---|
| Moving Average | 12% | 8% | -15% |
| Momentum | 18% | 22% | -35% |
# Moving Average Sharpe
ma_sharpe = (0.12 - 0.02) / 0.08 # = 1.25
# Momentum Sharpe
mom_sharpe = (0.18 - 0.02) / 0.22 # = 0.73
"""
The Moving Average strategy has better risk-adjusted returns
(Sharpe 1.25 vs 0.73) and much smaller drawdowns (-15% vs -35%).
Unless you have iron nerves, MA is the wiser choice.
"""
"Many have sought to turn base data into golden signals, but beware - the path is littered with the bones of those who confused alchemy with science."
The goddess Freya teaches you to brew potions of p-values and confidence intervals:
from sklearn.linear_model import LinearRegression
# Predict Bitcoin returns using S&P 500
model = LinearRegression()
model.fit(sp500_returns.reshape(-1,1), btc_returns)
print(f"Beta: {model.coef_[0]:.2f}")
print(f"Alpha: {model.intercept_:.4f}")
import numpy as np
def monte_carlo(S0, mu, sigma, days=252, sims=1000):
returns = np.random.normal(mu/days, sigma/np.sqrt(days), (days, sims))
return S0 * (1 + returns).cumprod(axis=0)
# Simulate 1000 possible price paths
simulations = monte_carlo(100, 0.1, 0.2)
import yfinance as yf
import numpy as np
from sklearn.linear_model import LinearRegression
# Get data
metals = yf.download(["GC=F", "SI=F"], start="2020-01-01")['Adj Close']
returns = metals.pct_change().dropna()
# Regression
model = LinearRegression()
model.fit(returns["GC=F"].values.reshape(-1,1), returns["SI=F"])
print(f"Silver moves {model.coef_[0]:.2f}x Gold daily")
# Simulation
def simulate(S0, mu, sigma, days=252, sims=10000):
daily_ret = np.random.normal(mu/days, sigma/np.sqrt(days), (days, sims))
return S0 * (1 + daily_ret).cumprod(axis=0)
gold_paths = simulate(1800, 0.08, 0.15)
silver_paths = simulate(25, 0.12, 0.25)
The Titan Chronos reveals three sacred truths:
ADF Test p-value ≤ 0.05
PACF cuts off after lag p
ACF cuts off after lag q
from statsmodels.tsa.arima.model import ARIMA
from statsmodels.tsa.stattools import adfuller
# Test for stationarity
result = adfuller(data['Close'])
print(f'ADF p-value: {result[1]:.4f}') # Need ≤ 0.05
# Fit ARIMA(1,1,1) model
model = ARIMA(data['Close'], order=(1,1,1))
results = model.fit()
# Forecast next 5 days
forecast = results.forecast(steps=5)
print(forecast)
import yfinance as yf
from statsmodels.tsa.arima.model import ARIMA
# Get data
eth = yf.download("ETH-USD", period="2y")['Close']
# Fit model (after testing p,d,q)
model = ARIMA(eth, order=(2,1,2))
results = model.fit()
# Forecast
forecast = results.forecast(steps=7)
print(f"Next week's ETH forecast:\n{forecast}")
Create predictive features from raw data:
# Technical Features
data['5D_Return'] = data['Close'].pct_change(5)
data['20D_Volatility'] = data['Close'].pct_change().rolling(20).std()
# Volume Features
data['Volume_MA_10'] = data['Volume'].rolling(10).mean()
data['Volume_Spike'] = data['Volume'] / data['Volume_MA_10']
# Target (next day return)
data['Target'] = (data['Close'].shift(-1) > data['Close']).astype(int)
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
# Prepare data
features = data[['5D_Return', '20D_Volatility', 'Volume_Spike']].dropna()
target = data['Target'].loc[features.index]
# Split data
X_train, X_test, y_train, y_test = train_test_split(
features, target, test_size=0.2, shuffle=False)
# Train model
model = RandomForestClassifier(n_estimators=100)
model.fit(X_train, y_train)
# Evaluate
print(f"Accuracy: {model.score(X_test, y_test):.2%}")
import yfinance as yf
from sklearn.ensemble import RandomForestClassifier
# Get data
data = yf.download("SPY", period="5y")
# Feature engineering
data['5D_MA'] = data['Close'].rolling(5).mean()
data['20D_MA'] = data['Close'].rolling(20).mean()
# ... (add 8 more features)
# Prepare model
features = data.dropna().iloc[:, 5:-1] # All features
target = (data['Close'].shift(-1) > data['Close']).astype(int).dropna()
model = RandomForestClassifier(n_estimators=200)
model.fit(features, target)
# Strategy: Buy when prediction > 0.6
"By Python's power and Pandas' might,
I swear to test my strategies right.
No look-ahead shall taint my score,
No hidden bias shall pass my door."
Enter the arena with these combat-tested techniques:
import backtrader as bt
class GoldenCross(bt.Strategy):
params = (('fast', 50), ('slow', 200))
def __init__(self):
self.fast_ma = bt.indicators.SMA(period=self.p.fast)
self.slow_ma = bt.indicators.SMA(period=self.p.slow)
self.crossover = bt.indicators.CrossOver(self.fast_ma, self.slow_ma)
def next(self):
if not self.position:
if self.crossover > 0: # Golden Cross
self.buy()
elif self.crossover < 0: # Death Cross
self.close()
# Add to cerebro
cerebro = bt.Cerebro()
cerebro.addstrategy(GoldenCross)
cerebro.addanalyzer(bt.analyzers.SharpeRatio, _name='sharpe')
results = cerebro.run()
print(f"Sharpe: {results[0].analyzers.sharpe.get_analysis()['sharperatio']:.2f}")
import backtrader as bt
import backtrader.analyzers as btanalyzers
class GoldenCrossStrategy(bt.Strategy):
params = (
('fast', 50),
('slow', 200),
('printlog', False),
)
def __init__(self):
self.fast_ma = bt.indicators.SMA(period=self.p.fast)
self.slow_ma = bt.indicators.SMA(period=self.p.slow)
self.crossover = bt.indicators.CrossOver(self.fast_ma, self.slow_ma)
def next(self):
if not self.position:
if self.crossover > 0:
self.buy()
elif self.crossover < 0:
self.close()
def stop(self):
if self.p.printlog:
print('Final Portfolio Value: %.2f' % self.broker.getvalue())
# Create cerebro engine
cerebro = bt.Cerebro()
# Add data feed
data = bt.feeds.YahooFinanceData(dataname='SPY', fromdate=datetime(2010, 1, 1),
todate=datetime(2020, 12, 31))
cerebro.adddata(data)
# Add strategy
cerebro.addstrategy(GoldenCrossStrategy, printlog=True)
# Set commission
cerebro.broker.setcommission(commission=0.001) # 0.1% commission
# Add analyzers
cerebro.addanalyzer(btanalyzers.SharpeRatio, _name='sharpe')
cerebro.addanalyzer(btanalyzers.DrawDown, _name='drawdown')
# Run backtest
results = cerebro.run()
# Print results
print('Sharpe Ratio:', results[0].analyzers.sharpe.get_analysis()['sharperatio'])
print('Max Drawdown:', results[0].analyzers.drawdown.get_analysis()['max']['drawdown'])
Protect your capital with these enchantments:
class StopLoss(bt.Strategy):
params = (('stop_loss', 0.05),) # 5%
def next(self):
if self.position:
if self.data.close[0] < self.position.price * (1 - self.p.stop_loss):
self.sell()
def next(self):
cash = self.broker.getcash()
value = self.broker.getvalue()
size = value * 0.1 / self.data.close[0] # 10% of portfolio
self.buy(size=size)
returns = portfolio.pct_change()
var_95 = np.percentile(returns.dropna(), 5)
print(f"95% Daily VaR: {var_95:.2%}")
Never risk more than 2% per trade
Minimum 5 uncorrelated assets
Multiple timeframes (daily + weekly)
import backtrader as bt
import numpy as np
class RiskManagedStrategy(bt.Strategy):
params = (
('stop_loss', 0.02), # 2% stop-loss
('max_position', 0.1), # 10% max position
)
def next(self):
# Position sizing
cash = self.broker.getcash()
value = self.broker.getvalue()
max_size = value * self.p.max_position / self.data.close[0]
if not self.position:
if self.should_buy(): # Your buy signal
self.buy(size=max_size)
else:
# Stop-loss check
if self.data.close[0] < self.position.price * (1 - self.p.stop_loss):
self.close()
def stop(self):
# Calculate portfolio VaR
returns = np.array([t.pnlcomm for t in self.trades]) / np.array([t.value for t in self.trades])
var_95 = np.percentile(returns, 5)
print(f"95% Trade VaR: {var_95:.2%}")
Forge your masterpiece trading system:
# Sample architecture
class LiveTradingBot:
def __init__(self):
self.data_feed = CCXTFeed(exchange='binance')
self.strategy = HybridMLStrategy()
self.risk_manager = DynamicRiskEngine()
self.execution = PaperTradingSimulator()
def run(self):
while True:
data = self.data_feed.fetch()
signals = self.strategy.generate(data)
orders = self.risk_manager.adjust(signals)
self.execution.submit(orders)
time.sleep(60) # Minute-by-minute
import alpaca_trade_api as tradeapi
import pandas as pd
import matplotlib.pyplot as plt
from IPython.display import clear_output
# Initialize Alpaca API
api = tradeapi.REST('YOUR_API_KEY', 'YOUR_SECRET_KEY', base_url='https://paper-api.alpaca.markets')
class LiveTrader:
def __init__(self):
self.portfolio = {}
self.history = pd.DataFrame()
def fetch_data(self, symbol):
bars = api.get_barset(symbol, 'minute', limit=1000).df[symbol]
return bars
def generate_signals(self, data):
# Implement your strategy here
signals = your_strategy(data)
return signals
def execute_trades(self, signals):
for symbol, signal in signals.items():
if signal == 'BUY':
api.submit_order(
symbol=symbol,
qty=100,
side='buy',
type='market',
time_in_force='gtc'
)
elif signal == 'SELL':
api.submit_order(
symbol=symbol,
qty=100,
side='sell',
type='market',
time_in_force='gtc'
)
def monitor(self):
while True:
clear_output(wait=True)
account = api.get_account()
print(f"Equity: ${account.equity}")
print(f"Buying Power: ${account.buying_power}")
# Update portfolio
positions = api.list_positions()
for pos in positions:
self.portfolio[pos.symbol] = {
'qty': pos.qty,
'value': pos.market_value,
'pnl': pos.unrealized_pl
}
# Plot portfolio
plt.figure(figsize=(10,5))
pd.DataFrame.from_dict(self.portfolio, orient='index')['value'].plot(kind='bar')
plt.title('Portfolio Allocation')
plt.show()
time.sleep(60)
# Run the trader
trader = LiveTrader()
trader.monitor()
"The markets shall rise and fall seven times seven, and with each turning, new opportunities shall emerge for those with eyes to see."
When AI traders outnumber flesh, the markets shall become a battlefield of algorithms
When quantum computers break our encryption, all crypto shall tremble
When retail traders finally learn risk management, the sharks shall go hungry
"The greatest algorithm is the one that adapts.
The wisest trader is the one who learns.
The richest soul is the one who shares."
From the depths of Excel's labyrinth we arose,
Armed with Python's might against chaotic flows.
Through ten trials of data, math, and code,
We forged our path on this perilous road.
The NaN sirens we silenced with dropna's call,
While Matplotlib's visions revealed it all.
ARIMA's prophecies and Random Forest's gaze,
Guided our hands through the market's maze.
Now stand we tall, our systems alive,
Algorithms thriving where others just strive.
So raise your goblets, fellow traders true,
The feast of profits awaits me and you!
"Every true warrior who masters these arts
Shall one day feast in Valhalla's smart charts!"
- Hallan Cosentino, Fin AI Tech
Support this grimoire's continued evolution
1N1AqocRgnEXopNGUVKTjYgXgspv6pdC2M
0xD9A1F789E71e224De987c29902D02Cb5cB7327CB
qrnx9k600pnxd66jtev4ky0nf3fhf33dy5v2lcn077
83uvR2ramAC3LZSxp8SZHs57zdvk4i2KuM2EUPixRgnZ59c91N2ybgRWkqMVUDL9wWQbonRyuY3og2ohnaGM52eFEzQpj6n