# DataFrame with columns: Open, High, Low, Close, Volume, etc. # (First few rows of AAPL historical data)

BaseIndicator, SMA, EMA, and RSI Classes

BaseIndicator is an abstract base class for all indicator classes. SMA, EMA, and RSI are concrete implementations.

Tested Example:

import numpy as np
from portfolio_lib.core import SMA, EMA, RSI
data = np.arange(1, 21)
sma = SMA(5)
ema = EMA(5)
rsi = RSI(5)
for v in data:
    sma.update(v)
    ema.update(v)
    rsi.update(v)
print("SMA:", sma.value)
print("EMA:", ema.value)
print("RSI:", rsi.value)

Output:

SMA: 18.0
EMA: 18.0
RSI: 100.0

Portfolio Class

Manages portfolio cash, positions, trades, and equity curve.

Attributes:

  • initial_cash: float — Starting cash

  • cash: float — Current cash

  • positions: dict — Open positions

  • trades: list — List of Trade objects

  • equity_curve: list — Portfolio value over time

  • timestamps: list — Timestamps for equity curve

Methods:

  • add_trade(trade): Add a trade to the portfolio

  • update_prices(prices, timestamp): Update prices for all positions

Properties:

  • total_equity: float — Total portfolio value

  • total_return: float — Total return in percent

  • total_value: float — Alias for total_equity

Tested Example:

from portfolio_lib.core import Portfolio, Trade
from datetime import datetime
portfolio = Portfolio(initial_cash=10000)
trade1 = Trade(symbol="AAPL", quantity=10, price=150.0, timestamp=datetime(2023, 1, 1), action="BUY")
trade2 = Trade(symbol="AAPL", quantity=5, price=155.0, timestamp=datetime(2023, 1, 2), action="SELL")
portfolio.add_trade(trade1)
portfolio.add_trade(trade2)
prices = {"AAPL": 160.0}
portfolio.update_prices(prices, datetime(2023, 1, 3))
print("Total Equity:", portfolio.total_equity)
print("Total Return:", portfolio.total_return)

Output:

Total Equity: 10275.0
Total Return: 2.75

DataFeed and YFinanceDataFeed Classes

DataFeed is a base class for data feeds. YFinanceDataFeed loads historical data from Yahoo Finance.

Tested Example:

from portfolio_lib.core import YFinanceDataFeed
datafeed = YFinanceDataFeed(["AAPL", "MSFT"])
datafeed.load_data("2023-01-01", "2023-01-10")
print(datafeed.data["AAPL"].head())

Output:

# DataFrame with columns: Open, High, Low, Close, Volume, etc.
# (First few rows of AAPL historical data)

Trade Class

Represents a completed trade.

Attributes:

  • symbol: str — The asset symbol

  • quantity: float — Number of shares/contracts

  • price: float — Trade price

  • timestamp: datetime — Trade time

  • action: str — ‘BUY’ or ‘SELL’

  • side: str — ‘buy’ or ‘sell’

  • commission: float — Commission paid

Properties:

  • gross_value: float — Quantity × price

  • net_value: float — gross_value minus commission

Tested Example:

from portfolio_lib.core import Trade
from datetime import datetime
trade = Trade(symbol="AAPL", quantity=10, price=150.0, timestamp=datetime(2023, 1, 1), action="BUY", commission=1.0)
print("Gross Value:", trade.gross_value)
print("Net Value:", trade.net_value)

Output:

Gross Value: 1500.0
Net Value: 1499.0

Portfolio Class

Manages portfolio cash, positions, trades, and equity curve.

Attributes:

  • initial_cash: float — Starting cash

  • cash: float — Current cash

  • positions: dict — Open positions

  • trades: list — List of Trade objects

  • equity_curve: list — Portfolio value over time

  • timestamps: list — Timestamps for equity curve

Methods:

  • add_trade(trade): Add a trade to the portfolio

  • update_prices(prices, timestamp): Update prices for all positions

Properties:

  • total_equity: float — Total portfolio value

  • total_return: float — Total return in percent

  • total_value: float — Alias for total_equity

Tested Example:

from portfolio_lib.core import Portfolio, Trade
from datetime import datetime
portfolio = Portfolio(initial_cash=10000)
trade1 = Trade(symbol="AAPL", quantity=10, price=150.0, timestamp=datetime(2023, 1, 1), action="BUY")
trade2 = Trade(symbol="AAPL", quantity=5, price=155.0, timestamp=datetime(2023, 1, 2), action="SELL")
portfolio.add_trade(trade1)
portfolio.add_trade(trade2)
prices = {"AAPL": 160.0}
portfolio.update_prices(prices, datetime(2023, 1, 3))
print("Total Equity:", portfolio.total_equity)
print("Total Return:", portfolio.total_return)

Output:

Total Equity: 10275.0
Total Return: 2.75

portfolio_lib.core module

Portfolio-lib - Lightweight Python Backtesting Library A comprehensive backtesting framework for algorithmic trading strategies

class portfolio_lib.core.BaseStrategy[source]

Bases: object

Base strategy class

__init__()[source]
init_indicators()[source]

Initialize technical indicators - to be implemented by subclasses

next()[source]

Strategy logic for each bar - to be implemented by subclasses

buy(symbol: str, size: float = 1.0, price: float | None = None)[source]

Place a buy order

sell(symbol: str, size: float | None = None, price: float | None = None)[source]

Place a sell order

position(symbol: str) Position | None[source]

Get current position for symbol

class portfolio_lib.core.Backtest(strategy: BaseStrategy, initial_cash: float = 100000.0)[source]

Bases: object

Main backtesting engine

__init__(strategy: BaseStrategy, initial_cash: float = 100000.0)[source]
add_data_source(data_feed: DataFeed)[source]

Add data source

run(start_date: str = '2020-01-01', end_date: str = None) BacktestResults[source]

Run the backtest

class portfolio_lib.core.YFinanceDataFeed(symbols: List[str])[source]

Bases: DataFeed

Yahoo Finance data feed

load_data(start_date: str, end_date: str)[source]

Load data from Yahoo Finance

fetch_data(start_date: str, end_date: str) Dict[str, DataFrame][source]

Alias for load_data that returns the data directly

class portfolio_lib.core.TechnicalIndicators[source]

Bases: object

Convenience class for technical indicator calculations

static sma(data: Series, period: int) Series[source]

Simple Moving Average

static ema(data: Series, period: int) Series[source]

Exponential Moving Average

static rsi(data: Series, period: int = 14) Series[source]

Relative Strength Index

static bollinger_bands(data: Series, period: int = 20, std_dev: float = 2)[source]

Bollinger Bands - returns (upper, middle, lower)

static macd(data: Series, fast: int = 12, slow: int = 26, signal: int = 9)[source]

MACD - returns (macd_line, signal_line, histogram)

class portfolio_lib.core.indicators[source]

Bases: object

class SMA(period: int)

Bases: BaseIndicator

Simple Moving Average

class EMA(period: int)

Bases: BaseIndicator

Exponential Moving Average

__init__(period: int)
class RSI(period: int)

Bases: BaseIndicator

Relative Strength Index

class MACD(fast_period: int = 12, slow_period: int = 26, signal_period: int = 9)

Bases: object

Moving Average Convergence Divergence

__init__(fast_period: int = 12, slow_period: int = 26, signal_period: int = 9)
property histogram: float | None
property macd: float | None
property signal: float | None
update(value: float)
class BollingerBands(period: int = 20, std_dev: float = 2.0)

Bases: object

Bollinger Bands indicator

__init__(period: int = 20, std_dev: float = 2.0)
property lower_band: float | None
property middle_band: float | None
update(value: float)
property upper_band: float | None
class WMA(period: int)

Bases: BaseIndicator

Weighted Moving Average

class DEMA(period: int)

Bases: BaseIndicator

Double Exponential Moving Average

__init__(period: int)
update(value: float)

Update indicator with new value

class TEMA(period: int)

Bases: BaseIndicator

Triple Exponential Moving Average

__init__(period: int)
update(value: float)

Update indicator with new value

class KAMA(period: int = 10, fast_sc: int = 2, slow_sc: int = 30)

Bases: BaseIndicator

Kaufman Adaptive Moving Average

__init__(period: int = 10, fast_sc: int = 2, slow_sc: int = 30)
class HullMA(period: int)

Bases: BaseIndicator

Hull Moving Average

__init__(period: int)
update(value: float)

Update indicator with new value

class VWAP

Bases: object

Volume Weighted Average Price

__init__()
update(price: float, volume: float)
property value: float | None
class ParabolicSAR(af_start: float = 0.02, af_increment: float = 0.02, af_max: float = 0.2)

Bases: object

Parabolic Stop and Reverse

__init__(af_start: float = 0.02, af_increment: float = 0.02, af_max: float = 0.2)
update(high: float, low: float, close: float)
property value: float | None
class McGinleyDynamic(period: int = 10)

Bases: BaseIndicator

McGinley Dynamic

__init__(period: int = 10)
class VerticalHorizontalFilter(period: int)

Bases: BaseIndicator

Vertical Horizontal Filter

class SuperTrend(period: int = 10, multiplier: float = 3.0)

Bases: object

SuperTrend Indicator

__init__(period: int = 10, multiplier: float = 3.0)
property trend_direction: int | None
update(high: float, low: float, close: float)
property value: float | None
class AlmaIndicator(period: int = 9, offset: float = 0.85, sigma: float = 6)

Bases: BaseIndicator

Arnaud Legoux Moving Average (ALMA)

__init__(period: int = 9, offset: float = 0.85, sigma: float = 6)
class Stochastic(k_period: int = 14, d_period: int = 3)

Bases: object

Stochastic Oscillator

__init__(k_period: int = 14, d_period: int = 3)
property d: float | None
property k: float | None
update(high: float, low: float, close: float)
class WilliamsR(period: int = 14)

Bases: BaseIndicator

Williams %R

__init__(period: int = 14)
update_hlc(high: float, low: float, close: float)
class CCI(period: int = 20)

Bases: BaseIndicator

Commodity Channel Index

__init__(period: int = 20)
update_hlc(high: float, low: float, close: float)
class ROC(period: int)

Bases: BaseIndicator

Rate of Change

class Momentum(period: int)

Bases: BaseIndicator

class StochasticRSI(rsi_period: int = 14, stoch_period: int = 14)

Bases: object

Stochastic RSI

__init__(rsi_period: int = 14, stoch_period: int = 14)
update(value: float)
property value: float | None
class TRIX(period: int = 14)

Bases: BaseIndicator

__init__(period: int = 14)
update(value: float)

Update indicator with new value

class UltimateOscillator(period1: int = 7, period2: int = 14, period3: int = 28)

Bases: object

Ultimate Oscillator

__init__(period1: int = 7, period2: int = 14, period3: int = 28)
update(high: float, low: float, close: float)
property value: float | None
class AwesomeOscillator(fast_period: int = 5, slow_period: int = 34)

Bases: object

Awesome Oscillator

__init__(fast_period: int = 5, slow_period: int = 34)
update(high: float, low: float)
property value: float | None
class WavesTrend(period1: int = 10, period2: int = 21)

Bases: object

WavesTrend Oscillator

__init__(period1: int = 10, period2: int = 21)
update(high: float, low: float, close: float)
property value: float | None
class DeMarker(period: int = 14)

Bases: object

DeMarker Indicator

__init__(period: int = 14)
update(high: float, low: float)
property value: float | None
class AroonIndicator(period: int = 25)

Bases: object

Aroon Indicator

__init__(period: int = 25)
property aroon_down: float | None
property aroon_oscillator: float | None
property aroon_up: float | None
update(high: float, low: float)
class ChandeMomentumOscillator(period: int)

Bases: BaseIndicator

Chande Momentum Oscillator

class KnowSureThing(roc1: int = 10, roc2: int = 15, roc3: int = 20, roc4: int = 30, sma1: int = 10, sma2: int = 10, sma3: int = 10, sma4: int = 15, signal: int = 9)

Bases: object

Know Sure Thing (KST)

__init__(roc1: int = 10, roc2: int = 15, roc3: int = 20, roc4: int = 30, sma1: int = 10, sma2: int = 10, sma3: int = 10, sma4: int = 15, signal: int = 9)
property kst: float | None
property signal: float | None
update(price: float)
class PercentagePriceOscillator(fast_period: int = 12, slow_period: int = 26, signal_period: int = 9)

Bases: object

Percentage Price Oscillator (PPO)

__init__(fast_period: int = 12, slow_period: int = 26, signal_period: int = 9)
property histogram: float | None
property ppo: float | None
property signal: float | None
update(price: float)
class DetrendedPriceOscillator(period: int)

Bases: BaseIndicator

Detrended Price Oscillator (DPO)

class PriceOscillator(fast_period: int = 10, slow_period: int = 20)

Bases: object

Price Oscillator

__init__(fast_period: int = 10, slow_period: int = 20)
update(price: float)
property value: float | None
class SchaffTrendCycle(cycle_period: int = 10, fast_period: int = 23, slow_period: int = 50)

Bases: object

Schaff Trend Cycle

__init__(cycle_period: int = 10, fast_period: int = 23, slow_period: int = 50)
update(price: float)
property value: float | None
class ElderRayIndex(period: int = 13)

Bases: object

Elder Ray Index (Bull Power and Bear Power)

__init__(period: int = 13)
property bear_power_value: float | None
property bull_power_value: float | None
update(high: float, low: float, close: float)
class KaufmanEfficiencyRatio(period: int)

Bases: BaseIndicator

Kaufman Efficiency Ratio

class RelativeVigorIndex(period: int = 10)

Bases: object

Relative Vigor Index

__init__(period: int = 10)
property rvi: float | None
property signal: float | None
update(open_price: float, high: float, low: float, close: float)
class AbsolutePriceOscillator(fast_period: int = 12, slow_period: int = 26)

Bases: object

Absolute Price Oscillator (APO)

__init__(fast_period: int = 12, slow_period: int = 26)
update(price: float)
property value: float | None
class CooppockCurve(wma_period: int = 10, roc1_period: int = 14, roc2_period: int = 11)

Bases: object

Coppock Curve

__init__(wma_period: int = 10, roc1_period: int = 14, roc2_period: int = 11)
update(price: float)
property value: float | None
class RainbowOscillator(period: int = 2)

Bases: object

Rainbow Oscillator

__init__(period: int = 2)
update(price: float)
property value: float | None
class StochasticMomentumIndex(k_period: int = 10, d_period: int = 3)

Bases: object

Stochastic Momentum Index

__init__(k_period: int = 10, d_period: int = 3)
property signal: float | None
property smi: float | None
update(high: float, low: float, close: float)
class ATR(period: int = 14)

Bases: object

Average True Range

__init__(period: int = 14)
update(high: float, low: float, close: float)
property value: float | None
class TrueRange

Bases: object

True Range

__init__()
update(high: float, low: float, close: float)
property value: float | None
class KeltnerChannels(period: int = 20, multiplier: float = 2.0)

Bases: object

Keltner Channels

__init__(period: int = 20, multiplier: float = 2.0)
property lower: float | None
property middle: float | None
update(high: float, low: float, close: float)
property upper: float | None
class DonchianChannels(period: int = 20)

Bases: object

Donchian Channels

__init__(period: int = 20)
property lower: float | None
property middle: float | None
update(high: float, low: float)
property upper: float | None
class ADX(period: int = 14)

Bases: object

Average Directional Index

__init__(period: int = 14)
update(high: float, low: float, close: float)
property value: float | None
class StandardError(period: int)

Bases: BaseIndicator

Standard Error

class MeanDeviation(period: int)

Bases: BaseIndicator

Mean Deviation

class ChoppinessIndex(period: int = 14)

Bases: BaseIndicator

Choppiness Index

__init__(period: int = 14)
update_hlc(high: float, low: float, close: float)
class RelativeVolatilityIndex(period: int = 10)

Bases: object

Relative Volatility Index

__init__(period: int = 10)
update(price: float)
property value: float | None
class KeltnerBands(period: int = 20, multiplier: float = 1.5)

Bases: object

Keltner Bands (alternative implementation)

__init__(period: int = 20, multiplier: float = 1.5)
property lower: float | None
property middle: float | None
update(high: float, low: float, close: float)
property upper: float | None
class OBV

Bases: object

On-Balance Volume

__init__()
update(close: float, volume: float)
property value: float
class AccumulationDistribution

Bases: object

Accumulation/Distribution Line

__init__()
update(high: float, low: float, close: float, volume: float)
property value: float
class ChaikinMoneyFlow(period: int = 20)

Bases: object

Chaikin Money Flow

__init__(period: int = 20)
update(high: float, low: float, close: float, volume: float)
property value: float | None
class VROC(period: int = 25)

Bases: BaseIndicator

Volume Rate of Change

__init__(period: int = 25)
update_volume(volume: float)
class ForceIndex(period: int = 13)

Bases: object

Force Index

__init__(period: int = 13)
update(close: float, volume: float)
property value: float | None
class VWMA(period: int)

Bases: BaseIndicator

Volume Weighted Moving Average

__init__(period: int)
update_with_volume(price: float, volume: float)
class MoneyFlowIndex(period: int = 14)

Bases: object

Money Flow Index

__init__(period: int = 14)
update(high: float, low: float, close: float, volume: float)
property value: float | None
class VolumeOscillator(fast_period: int = 5, slow_period: int = 10)

Bases: object

Volume Oscillator

__init__(fast_period: int = 5, slow_period: int = 10)
update(volume: float)
property value: float | None
class EaseOfMovement(period: int = 14)

Bases: object

Ease of Movement

__init__(period: int = 14)
update(high: float, low: float, volume: float)
property value: float | None
class NegativeVolumeIndex

Bases: object

Negative Volume Index

__init__()
update(close: float, volume: float)
property value: float
class PositiveVolumeIndex

Bases: object

Positive Volume Index

__init__()
update(close: float, volume: float)
property value: float
class MarketFacilitationIndex

Bases: object

Market Facilitation Index

__init__()
update(high: float, low: float, volume: float)
property value: float | None
class PVT

Bases: object

Price Volume Trend

__init__()
update(close: float, volume: float)
property value: float
class StandardDeviation(period: int)

Bases: BaseIndicator

Standard Deviation

class Variance(period: int)

Bases: BaseIndicator

class ZScore(period: int)

Bases: BaseIndicator

Z-Score

class LinearRegression(period: int)

Bases: object

Linear Regression

__init__(period: int)
property intercept: float | None
property slope: float | None
update(value: float)
property value: float | None
class Correlation(period: int)

Bases: object

Correlation between two series

__init__(period: int)
update(x: float, y: float)
property value: float | None
class PivotPoints

Bases: object

Pivot Points

__init__()
update(high: float, low: float, close: float)
class FibonacciRetracement

Bases: object

Fibonacci Retracement

__init__()
get_retracement_levels() Dict[str, float]
update(high: float, low: float)
class ZigZag(deviation: float = 5.0)

Bases: object

ZigZag Indicator

__init__(deviation: float = 5.0)
property trend: str | None
update(high: float, low: float, close: float)
class SwingIndex

Bases: object

Swing Index

__init__()
update(open_price: float, high: float, low: float, close: float)
property value: float | None
class AccumulativeSwingIndex

Bases: object

Accumulative Swing Index

__init__()
update(open_price: float, high: float, low: float, close: float)
property value: float
class FractalIndicator(period: int = 5)

Bases: object

Fractal Indicator

__init__(period: int = 5)
property is_bear_fractal: bool
property is_bull_fractal: bool
update(high: float, low: float)
class HilbertTransform

Bases: object

Hilbert Transform - Dominant Cycle Period

__init__()
property dominant_cycle: float | None
update(price: float)
class TypicalPrice

Bases: BaseIndicator

Typical Price (HLC/3)

__init__()
update_hlc(high: float, low: float, close: float)
class WeightedClose

Bases: BaseIndicator

Weighted Close (HLCC/4)

__init__()
update_hlc(high: float, low: float, close: float)
class MedianPrice

Bases: BaseIndicator

Median Price (HL/2)

__init__()
update_hl(high: float, low: float)
property value: float | None

Get current indicator value

class BalanceOfPower

Bases: object

Balance of Power

__init__()
update(open_price: float, high: float, low: float, close: float)
property value: float | None
class IchimokuKinkoHyo(tenkan_period: int = 9, kijun_period: int = 26, senkou_b_period: int = 52, displacement: int = 26)

Bases: object

Ichimoku Kinko Hyo

__init__(tenkan_period: int = 9, kijun_period: int = 26, senkou_b_period: int = 52, displacement: int = 26)
property chikou: float | None
property kijun: float | None
property senkou_a: float | None
property senkou_b: float | None
property tenkan: float | None
update(high: float, low: float, close: float)
class portfolio_lib.core.Position(symbol: str, quantity: float, entry_price: float, timestamp: datetime = None)[source]

Bases: object

Represents a trading position

__init__(symbol: str, quantity: float, entry_price: float, timestamp: datetime = None)[source]
property market_value: float
property unrealized_pnl: float
property unrealized_pnl_pct: float
property value: float

Alias for market_value for compatibility

class portfolio_lib.core.Trade(symbol: str, quantity: float, price: float, timestamp: datetime, action: str = None, side: str = None, commission: float = 0.0)[source]

Bases: object

Represents a completed trade

__init__(symbol: str, quantity: float, price: float, timestamp: datetime, action: str = None, side: str = None, commission: float = 0.0)[source]
property gross_value: float
property net_value: float
class portfolio_lib.core.Portfolio(initial_cash: float = 100000.0)[source]

Bases: object

Portfolio management class

__init__(initial_cash: float = 100000.0)[source]
add_trade(trade: Trade)[source]

Add a trade to the portfolio

update_prices(prices: Dict[str, float], timestamp: datetime)[source]

Update current prices for all positions

property total_equity: float

Calculate total portfolio equity

property total_return: float

Calculate total return percentage

property total_value: float

Alias for total_equity for compatibility

class portfolio_lib.core.PerformanceMetrics(equity_curve: List[float], timestamps: List[datetime], trades: List[Trade], initial_cash: float)[source]

Bases: object

Calculate performance metrics

__init__(equity_curve: List[float], timestamps: List[datetime], trades: List[Trade], initial_cash: float)[source]
property total_return: float

Total return percentage

property annualized_return: float

Annualized return

property volatility: float

Annualized volatility

property sharpe_ratio: float

Sharpe ratio (assuming 0% risk-free rate)

property max_drawdown: float

Maximum drawdown percentage

property sortino_ratio: float

Sortino ratio

property calmar_ratio: float

Calmar ratio

property win_rate: float

Win rate percentage

property profit_factor: float

Profit factor

class portfolio_lib.core.BacktestResults(portfolio: Portfolio, metrics: PerformanceMetrics)[source]

Bases: object

Backtest results container

__init__(portfolio: Portfolio, metrics: PerformanceMetrics)[source]
summary() str[source]

Generate summary report

Core Classes, Examples, and Visuals

Note

The following classes provide essential portfolio management functionality.

Position Class

Represents a trading position.

Attributes:

  • symbol: str — The asset symbol

  • quantity: float — Number of shares/contracts

  • entry_price: float — Entry price

  • timestamp: datetime — Entry time

  • current_price: float — Current price

Properties:

  • market_value: float — Current market value

  • unrealized_pnl: float — Unrealized profit/loss

  • unrealized_pnl_pct: float — Unrealized P&L in percent

  • value: float — Alias for market_value

Tested Example:

from portfolio_lib.core import Position
from datetime import datetime
pos = Position(symbol="AAPL", quantity=10, entry_price=150.0, timestamp=datetime(2023, 1, 1))
pos.current_price = 155.0
print("Market Value:", pos.market_value)
print("Unrealized PnL:", pos.unrealized_pnl)
print("Unrealized PnL %:", pos.unrealized_pnl_pct)

Output:

Market Value: 1550.0
Unrealized PnL: 50.0
Unrealized PnL %: 3.3333333333333335

Trade Class

Represents a completed trade.

Attributes:

  • symbol: str — The asset symbol

  • quantity: float — Number of shares/contracts

  • price: float — Trade price

  • timestamp: datetime — Trade time

  • action: str — ‘BUY’ or ‘SELL’

  • side: str — ‘buy’ or ‘sell’

  • commission: float — Commission paid

Properties:

  • gross_value: float — Quantity × price

  • net_value: float — gross_value minus commission

Tested Example:

from portfolio_lib.core import Trade
from datetime import datetime
trade = Trade(symbol="AAPL", quantity=10, price=150.0, timestamp=datetime(2023, 1, 1), action="BUY", commission=1.0)
print("Gross Value:", trade.gross_value)
print("Net Value:", trade.net_value)

Output:

Gross Value: 1500.0
Net Value: 1499.0