fastquant Documentation

repository·master·Indexed 23 days ago

https://github.com/enzoampil/fastquant

A Python library for quantitative financial backtesting. It provides tools to download historical stock data from Yahoo Finance and the PSE, and cryptocurrency data from Binance and other exchanges. The library features a `backtest()` function supporting built-in strategies (RSI, SMAC, EMAC, MACD, Bollinger Bands), multi-strategy combinations, automated grid search for parameter optimization, and custom machine learning prediction strategies. It also includes `walk_forward_split` for time series validation and support for custom strategies via `BaseStrategy` subclassing.

Tokens
10.7K
Snippets
33
Records
56
Agent score
82%

What's inside fastquant

  1. How sliding vs expanding modes work in walk_forward_split

    master

    The mode parameter determines how the training window moves through the time series:

    • Sliding Mode (Default): The training window moves forward, and the training set size remains constant (or follows the specified logic), effectively 'sliding' over the data.
    • Expanding Mode (mode='expanding'): The training window includes all indices from previous splits, meaning the training set grows larger with each subsequent split.
  2. Use the Multi-Strategy approach

    master

    You can combine multiple strategies using the multi alias. Strategies are applied in an OR fashion: a buy or sell signal is triggered if at least one of the configured strategies triggers it. You can provide fixed parameters or use iterators for grid search across multiple strategies simultaneously.

    from fastquant import get_stock_data, backtest
    
    df = get_stock_data("JFC", "2018-01-01", "2019-01-01")
    
    # 1. Using single set of parameters
    strats = { 
        "smac": {"fast_period": 35, "slow_period": 50}, 
        "rsi": {"rsi_lower": 30, "rsi_upper": 70} 
    } 
    res = backtest("multi", df, strats=strats)
    
    # 2. Using auto grid search across multiple strategies
    strats_opt = { 
        "smac": {"fast_period": 35, "slow_period": [40, 50]}, 
        "rsi": {"rsi_lower": [15, 30], "rsi_upper": 70} 
    } 
    res_opt = backtest("multi", df, strats=strats_opt)
  3. Backtest custom machine learning predictions

    master

    The custom strategy allows you to backtest any model-based prediction. To use it:

    1. Generate your predictions (e.g., using Prophet, Scikit-learn, etc.).
    2. Add the predictions to a new column in your DataFrame named custom.
    3. Call backtest('custom', df, upper_limit=X, lower_limit=Y).

    By default, the strategy buys when the custom value is below lower_limit (default 5) and sells when it is above upper_limit (default 95).

  4. Optimize trading strategies with automated grid search

    master

    You can perform an automated grid search to find the optimal parameters for a strategy by passing iterators (like list or range) instead of single values to the backtest function. The function will return a DataFrame containing the results for all parameter combinations.

    from fastquant import backtest
    # Optimize SMAC parameters using ranges
    res = backtest("smac", df, fast_period=range(15, 30, 3), slow_period=range(40, 55, 3), verbose=False)
    
    # View optimal results
    print(res[['fast_period', 'slow_period', 'final_value']].head())
  5. Get Twitter API Credentials

    master

    To use the get_twitter_sentiment() function in fastquant, you must obtain Twitter API credentials from the Twitter Developer Portal.

    Follow these steps:

    1. Log in to your Twitter account and visit developer.twitter.com/en/apps.
    2. Click Create an App.
    3. Provide an App name, a brief Application Description, and a Website URL (a placeholder like placeholder.com is acceptable).
    4. Complete the Tell us how this app will be used section with a brief explanation.
    5. Click Create.
    6. Once the app is created, click on Details for your app.
    7. Navigate to the Keys and Tokens tab.
    8. Locate and save your API key and API secret key.
    9. Under Access tokens, click Generate (or Regenerate) to obtain your Access token and Access token secret.

    Important: Secure these four keys immediately, as regenerating tokens will invalidate existing ones.

  6. Install fastquant and set up Jupyter Notebooks

    master

    To use the full plotting capabilities of fastquant, it is recommended to use a local Jupyter notebook rather than Google Colab.

    1. Install Jupyter via pip: pip3 install jupyter
    2. Clone the repository: git clone https://github.com/enzoampil/fastquant.git
    3. Navigate to the directory: cd fastquant
    4. Launch the notebook server: jupyter notebook
    5. Open the lesson file: lessons/fastquant_lesson2_backtest_your_trading_strategy.ipynb
    pip3 install jupyter
    git clone https://github.com/enzoampil/fastquant.git
    cd fastquant
    jupyter notebook
  7. Run fastquant in a Docker container

    master

    You can containerize the fastquant environment using the provided Dockerfile.

    # Build the image
    docker build -t myimage .
    
    # Run the container
    docker run -t -d -p 5000:5000 myimage
    
    # Get the container id
    docker ps
    
    # SSH into the fastquant container
    docker exec -it <CONTAINER_ID> /bin/bash
  8. Create a custom strategy by extending BaseStrategy

    master

    To implement a custom trading strategy, inherit from fastquant.strategies.base.BaseStrategy. You must define:

    • params: A tuple of strategy parameters.
    • __init__: To initialize indicators (using backtrader indicators) and strategy variables.
    • buy_signal(): Returns True when a long entry condition is met.
    • sell_signal(): Returns True when a short/exit condition is met.
    • exit_long_signal(): (Optional) Returns True when a long position should be closed.
    import backtrader as bt
    from fastquant.strategies.base import BaseStrategy
    
    class RSIStrategy(BaseStrategy):
        params = (("rsi_period", 14), ("rsi_upper", 70), ("rsi_lower", 30))
    
        def __init__(self):
            super().__init__()
            self.rsi_period = self.params.rsi_period
            self.rsi_upper = self.params.rsi_upper
            self.rsi_lower = self.params.rsi_lower
            self.rsi = bt.indicators.RelativeStrengthIndex(period=self.rsi_period, upperband=self.rsi_upper, lowerband=self.rsi_lower)
    
        def buy_signal(self):
            return self.rsi[0] < self.rsi_lower
    
        def sell_signal(self):
            return self.rsi[0] > self.rsi_upper
    
        def exit_long_signal(self):
            return self.rsi[0] >= 50
  9. Implement a custom strategy by subclassing BaseStrategy

    master

    To create a custom trading strategy, create a new class that inherits from BaseStrategy.

    Key steps in the implementation:

    1. Define params: A tuple of parameters used to configure the strategy (e.g., indicator periods or column names).
    2. Initialize indicators in __init__: Use built-in indicators (like MACD or CrossOver) or CustomIndicator to wrap columns in your dataframe.
    3. Define buy_signal(self): Return True when all buy conditions are met.
    4. Define sell_signal(self): Return True when the sell condition is met.

    Note: Inside the signal methods, self.dataclose[0] refers to the current closing price.

    from fastquant import CustomStrategy, BaseStrategy
    from fastquant.indicators import MACD, CrossOver 
    from fastquant.indicators.custom import CustomIndicator
    
    class MAMAStrategy(BaseStrategy):
        params = (
            ("alma_column", "alma"),
            ("macd_fast_period", 12),
            ("macd_slow_period", 16),
            ("macd_signal_period", 9)
        )
    
        def __init__(self):
            super().__init__()
            # Setup indicators
            self.macd_ind = MACD(
                period_me1=self.params.macd_fast_period, 
                period_me2=self.params.macd_slow_period, 
                period_signal=self.params.macd_signal_period
            )
            self.macd_signal_crossover = CrossOver(self.macd_ind, self.macd_ind.signal)
            
            # Wrap a custom column from the dataframe
            self.alma = CustomIndicator(self.data, custom_column=self.params.alma_column)
            self.alma.plotinfo.subplot = False
            self.alma.plotinfo.plotname = "ALMA"
    
        def buy_signal(self):
            # Example: Close is above ALMA AND MACD crosses signal line upward
            alma_buy = self.dataclose[0] > self.alma[0]
            macd_buy = self.macd_signal_crossover[0] > 0
            return alma_buy and macd_buy
    
        def sell_signal(self):
            # Example: Close falls below ALMA
            return self.alma[0] > self.dataclose[0]