Skip to content

Strategy idea: Pattern similarity-based signals via Chart Library APIΒ #1355

@grahammccain

Description

@grahammccain

Idea

Backtesting.py makes it easy to test indicator-based strategies. Here's a strategy concept that uses historical pattern similarity as the signal: find the most similar past chart patterns and trade based on their aggregate forward returns.

Chart Library has 24M+ pre-computed embeddings across 19K US stocks (10 years). Its API returns the top matches with actual forward returns for any (symbol, date).

Example strategy

from backtesting import Backtest, Strategy
import requests

class PatternSimilarity(Strategy):
    """
    Buy when historically similar patterns had positive forward returns.
    Sell when they had negative forward returns.
    """
    lookback_threshold = 0.6  # min win rate to enter long
    
    def init(self):
        self.pattern_signals = {}
        
    def next(self):
        date_str = str(self.data.index[-1].date())
        
        if date_str not in self.pattern_signals:
            try:
                resp = requests.get("https://chartlibrary.io/api/v1/search", 
                    params={"symbol": "AAPL", "date": date_str, "timeframe": "RTH"},
                    headers={"X-API-Key": "your-key"}, timeout=5)
                matches = resp.json()["matches"]
                win_rate = sum(1 for m in matches if m["return_5d"] > 0) / len(matches)
                avg_return = sum(m["return_5d"] for m in matches) / len(matches)
                self.pattern_signals[date_str] = {
                    "win_rate": win_rate, "avg_return": avg_return
                }
            except Exception:
                return
        
        sig = self.pattern_signals.get(date_str)
        if not sig:
            return
            
        if not self.position and sig["win_rate"] >= self.lookback_threshold:
            self.buy()
        elif self.position and sig["win_rate"] < 0.4:
            self.position.close()

For production, you'd pre-fetch all signals into a DataFrame column rather than calling the API in the loop.

What the API provides per match

  • Symbol, date, timeframe of the historical match
  • L2 distance (similarity score)
  • Forward returns: 1-day, 3-day, 5-day, 10-day

Details

This is essentially a "nearest neighbor" trading strategy β€” find the most similar historical charts and bet on the average outcome.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions