CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-bt

A flexible backtesting framework for Python designed for quantitative trading strategy development and testing.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

specialized-securities.mddocs/

Specialized Securities

Advanced security types for specialized use cases including fixed income securities, hedge securities, and coupon-paying instruments. These securities provide custom valuation methods, cash flow handling, and specialized strategy behavior.

Capabilities

Fixed Income Securities

Securities designed for fixed income instruments with par value-based notional value calculation instead of market value.

class FixedIncomeSecurity(SecurityBase):
    """
    Fixed income security with par value-based notional value.
    
    Inherits from SecurityBase but overrides notional value calculation
    to use par value (PAR * position) instead of market value.
    
    Args:
        name (str): Security name/ticker
        multiplier (float): Security multiplier (default 1)
        lazy_add (bool): Whether to add to parent lazily
    """
    def update(self, date, data=None, inow=None):
        """Update security state with fixed income specific logic."""
        ...

class FixedIncomeStrategy(Strategy):
    """
    Strategy optimized for fixed income with notional weighting.
    
    Uses notional values instead of market values for weight calculations,
    appropriate for fixed income portfolio management.
    
    Args:
        name (str): Strategy name
        algos (list, optional): Algorithm list
        children (list, optional): Child securities
    """
    def __init__(self, name: str, algos=None, children=None): ...

Coupon-Paying Securities

Securities that handle irregular coupons and cash disbursements, tracking both price movements and cash flows.

class CouponPayingSecurity(FixedIncomeSecurity):
    """
    Security handling irregular coupons and cash disbursements.
    
    Tracks coupon payments and holding costs in addition to price movements.
    Inherits fixed income notional value calculation.
    
    Args:
        name (str): Security name/ticker
        multiplier (float): Security multiplier (default 1)
        fixed_income (bool): Whether to use fixed income logic (default True)
        lazy_add (bool): Whether to add to parent lazily
    """
    def __init__(self, name: str, multiplier=1, fixed_income=True, lazy_add=False): ...
    
    def setup(self, universe, **kwargs):
        """Setup security with coupon data from universe."""
        ...
    
    def update(self, date, data=None, inow=None):
        """Update security with coupon processing logic."""
        ...
    
    # Properties
    @property
    def coupon(self): ...
    @property
    def coupons(self): ...
    @property
    def holding_cost(self): ...
    @property
    def holding_costs(self): ...

Hedge Securities

Securities with zero notional value that don't contribute to strategy value calculations, useful for hedging instruments.

class HedgeSecurity(SecurityBase):
    """
    Security with zero notional value.
    
    Hedge securities don't count toward strategy value calculations,
    making them useful for overlay strategies and hedging instruments.
    
    Args:
        name (str): Security name/ticker
        multiplier (float): Security multiplier (default 1)
        lazy_add (bool): Whether to add to parent lazily
    """
    def update(self, date, data=None, inow=None):
        """Update security with hedge-specific logic (zero notional value)."""
        ...

class CouponPayingHedgeSecurity(CouponPayingSecurity):
    """
    Coupon-paying security with zero notional value.
    
    Combines coupon payment handling with hedge security behavior.
    Useful for fixed income overlay strategies.
    
    Args:
        name (str): Security name/ticker
        multiplier (float): Security multiplier (default 1)
        fixed_income (bool): Whether to use fixed income logic (default True)
        lazy_add (bool): Whether to add to parent lazily
    """
    def update(self, date, data=None, inow=None):
        """Update security with coupon processing and zero notional value."""
        ...

Usage Examples

Fixed Income Portfolio

import bt
import pandas as pd

# Create fixed income securities
tlt = bt.FixedIncomeSecurity('TLT')  # 20+ Year Treasury Bond ETF
iei = bt.FixedIncomeSecurity('IEI')  # 3-7 Year Treasury Bond ETF
tip = bt.FixedIncomeSecurity('TIP')  # Treasury Inflation-Protected Securities

# Create fixed income strategy
fi_strategy = bt.FixedIncomeStrategy('FixedIncome', 
    algos=[
        bt.algos.RunMonthly(),
        bt.algos.SelectAll(),
        bt.algos.WeighEqually(),
        bt.algos.Rebalance()
    ],
    children=[tlt, iei, tip]
)

# Set notional value for portfolio
fi_strategy.algos.insert(0, bt.algos.SetNotional(10000000))  # $10M notional

# Run backtest
data = bt.get('TLT,IEI,TIP', start='2010-01-01', end='2020-01-01')
backtest = bt.Backtest(fi_strategy, data)
result = bt.run(backtest)

Coupon-Paying Securities

# Create coupon-paying security with coupon data
coupon_data = pd.DataFrame({
    'BOND_COUPON': [0.025, 0.025, 0.025, 0.025],  # 2.5% quarterly coupons
    'BOND_HOLDING_COST': [0.001, 0.001, 0.001, 0.001]  # Holding costs
}, index=pd.date_range('2020-01-01', periods=4, freq='Q'))

bond = bt.CouponPayingSecurity('BOND')

# Setup with coupon data
universe_data = {'BOND': price_data, 'BOND_COUPON': coupon_data['BOND_COUPON']}
bond.setup(universe_data)

# Create strategy
strategy = bt.Strategy('CouponBond', 
    algos=[
        bt.algos.RunDaily(),
        bt.algos.SelectAll(),
        bt.algos.WeighEqually(),
        bt.algos.Rebalance()
    ],
    children=[bond]
)

Hedge Overlay Strategy

# Create main portfolio securities
spy = bt.Security('SPY')
qqq = bt.Security('QQQ')

# Create hedge securities (don't count toward portfolio value)
vix_hedge = bt.HedgeSecurity('VXX')  # VIX hedge
put_hedge = bt.HedgeSecurity('PUTS')  # Put option hedge

# Main strategy with hedge overlay
main_strategy = bt.Strategy('MainStrategy', 
    algos=[
        bt.algos.RunMonthly(),
        bt.algos.SelectTypes(include_types=(bt.Security,)),  # Only main securities
        bt.algos.WeighEqually(),
        bt.algos.Rebalance()
    ],
    children=[spy, qqq, vix_hedge, put_hedge]
)

# Hedge strategy (runs separately)
hedge_strategy = bt.Strategy('HedgeStrategy',
    algos=[
        bt.algos.RunDaily(),
        bt.algos.SelectTypes(include_types=(bt.HedgeSecurity,)),  # Only hedge securities
        bt.algos.WeighSpecified(VXX=0.05, PUTS=0.02),  # Small hedge positions
        bt.algos.Rebalance()
    ],
    parent=main_strategy
)

Mixed Security Types

# Portfolio with different security types
securities = [
    bt.Security('SPY'),                        # Regular equity
    bt.FixedIncomeSecurity('TLT'),            # Fixed income
    bt.CouponPayingSecurity('CORP_BOND'),     # Corporate bond with coupons
    bt.HedgeSecurity('VIX_HEDGE'),            # Hedge instrument
    bt.CouponPayingHedgeSecurity('FI_HEDGE')  # Fixed income hedge with coupons
]

# Strategy that handles all types
mixed_strategy = bt.Strategy('MixedPortfolio', 
    algos=[
        bt.algos.RunMonthly(),
        
        # Handle regular securities
        bt.algos.SelectTypes(include_types=(bt.Security,)),
        bt.algos.WeighSpecified(SPY=0.6),
        bt.algos.Rebalance(),
        
        # Handle fixed income
        bt.algos.SelectTypes(include_types=(bt.FixedIncomeSecurity,)),
        bt.algos.WeighSpecified(TLT=0.3, CORP_BOND=0.1),
        bt.algos.Rebalance(),
        
        # Handle hedges (separate allocation)
        bt.algos.SelectTypes(include_types=(bt.HedgeSecurity,)),
        bt.algos.WeighSpecified(VIX_HEDGE=0.02, FI_HEDGE=0.01),
        bt.algos.Rebalance()
    ],
    children=securities
)

Advanced Fixed Income Strategy

# Create duration-matched fixed income portfolio
short_duration = bt.FixedIncomeSecurity('SHY')  # 1-3 Year
med_duration = bt.FixedIncomeSecurity('IEI')    # 3-7 Year  
long_duration = bt.FixedIncomeSecurity('TLT')   # 20+ Year

# Duration targeting strategy
duration_strategy = bt.FixedIncomeStrategy('DurationTarget',
    algos=[
        # Set target notional
        bt.algos.SetNotional(1000000),
        
        # Monthly rebalancing
        bt.algos.RunMonthly(),
        bt.algos.SelectAll(),
        
        # Dynamic duration weighting based on yield curve
        bt.algos.WeighTarget(duration_weights),  # External weight calculation
        bt.algos.Rebalance()
    ],
    children=[short_duration, med_duration, long_duration]
)

# Run with yield curve data
yield_data = bt.get('SHY,IEI,TLT', start='2010-01-01', end='2020-01-01')
backtest = bt.Backtest(duration_strategy, yield_data)
result = bt.run(backtest)

# Analyze results with fixed income focus
print("Portfolio Duration:", result.get_weights(0).mean())
result.plot_weights(0, title='Duration Allocation Over Time')

Key Differences

Notional Value Calculations

  • Security: notional_value = price * position (market value)
  • FixedIncomeSecurity: notional_value = PAR * position (par value)
  • HedgeSecurity: notional_value = 0 (excluded from portfolio value)
  • CouponPayingSecurity: Par value + coupon tracking

Strategy Behavior

  • Strategy: Uses market values for weight calculations
  • FixedIncomeStrategy: Uses notional values for weight calculations
  • Hedge securities: Don't affect parent strategy value but can have positions

Cash Flow Handling

  • Regular securities: Only track price changes
  • Coupon-paying securities: Track both price changes and coupon payments
  • Holding costs: Additional cost tracking for financing and maintenance

Install with Tessl CLI

npx tessl i tessl/pypi-bt

docs

algorithm-components.md

backtesting-engine.md

core-framework.md

index.md

specialized-securities.md

tile.json