trading-strategy

repository·master·Indexed 18 days ago

https://github.com/tradingstrategy-ai/trading-strategy

A Python framework (v0.28) for algorithmic trading on decentralized exchanges (DEXes) such as Uniswap, Aave, and PancakeSwap. It provides a data layer for downloading DeFi market datasets, accessing real-time price feeds, and managing OHLCV candle data for backtesting and live trading across Ethereum, Binance Smart Chain, and Polygon. The library includes a Client for interacting with the Trading Strategy oracle, supporting TVL data, CLMM liquidity provision candles, and lending market data.

Tokens
4.5K
Snippets
14
Records
17
Agent score
63%

What's inside trading-strategy

  1. Overview of the Trading Strategy framework

    master

    The trading-strategy framework is designed for algorithmic trading on decentralized exchanges (DEXes). It provides the data layer necessary for:

    • Data Acquisition: Downloading DeFi market datasets and accessing real-time price feeds from the Trading Strategy Protocol.
    • Backtesting: Developing and testing strategies within Jupyter Notebooks using historical data.
    • Live Trading Support: Providing the data foundation for on-chain trading execution.
    • Vault Support: Enabling the deployment of strategies as smart contract vaults for third-party investment.

    Supported blockchains include Ethereum mainnet, Binance Smart Chain, and Polygon. Supported DEXes include SushiSwap, QuickSwap, and PancakeSwap.

  2. Install the trading-strategy package

    master

    You can install the trading-strategy package using pip or poetry. To access full functionality including direct data feeds, use the direct-feed extra.

    Important Note: The trading-strategy package is strictly for downloading and managing trading data. To develop and run automated trading strategies, you must also install the trade-executor package.

    # Using pip
    pip install "trading-strategy[direct-feed]"
    
    # Using Poetry as a dependency
    poetry add trading-strategy -E direct-feed
    
    # For local development with Poetry
    poetry install -E direct-feed
  3. Initialize the Client

    master

    The Client class is the primary entry point for interacting with the Trading Strategy oracle. You should not call the constructor directly; instead, use the factory method create_live_client(api_key) to instantiate a client for production use. The client handles data downloading, local disk caching to prevent redundant downloads, and automatic retries for corrupted Parquet files.

    import os
    from tradingstrategy.client import Client
    
    # Ensure TRADING_STRATEGY_API_KEY is set in your environment
    api_key = os.environ["TRADING_STRATEGY_API_KEY"]
    client = Client.create_live_client(api_key)
  4. Aggregate sparse transaction data into OHLC intervals

    master

    When dealing with transaction data that lacks regular intervals or has missing days, you can use pandas .resample() combined with .agg() to transform raw transaction timestamps into Open, High, Low, and Close (OHLC) format.

    To perform this aggregation:

    1. Ensure your DataFrame has a DatetimeIndex.
    2. Use .resample() with the desired frequency (e.g., '1D' for daily).
    3. Use .agg() with a dictionary mapping the OHLC keys to their respective pandas reduction functions: 'first' for open, 'max' for high, 'min' for low, and 'last' for close.
    import pandas as pd
    
    # Sample sparse transaction data
    data = {
        "timestamp": [
            pd.Timestamp("2020-01-01 01:00"),
            pd.Timestamp("2020-01-01 05:00"),
            pd.Timestamp("2020-01-02 03:00"),
            pd.Timestamp("2020-01-04 04:00"),
            pd.Timestamp("2020-01-05 00:00"),
        ],
        "transaction": [100.00, 102.00, 103.00, 102.80, 99.88]
    }
    
    df = pd.DataFrame.from_dict(data, orient="columns")
    df.set_index("timestamp", inplace=True)
    
    # Resample to daily frequency and aggregate to OHLC
    ohlc_resample = df["transaction"].resample("1D").agg({
        'open': 'first', 
        'high': 'max', 
        'low': 'min', 
        'close': 'last'
    })
    
    print(ohlc_resample)
  5. How to use the Client for data analysis

    master

    A typical workflow involves creating a live client, fetching the exchange and pair universe, and then downloading specific candle data for analysis.

    from tradingstrategy.chain import ChainId
    from tradingstrategy.client import Client
    from tradingstrategy.pair import PandasPairUniverse
    from tradingstrategy.timebucket import TimeBucket
    import pandas as pd
    import os
    
    # 1. Initialize Client
    client = Client.create_live_client(
        settings_path=None,
        api_key=os.environ["TRADING_STRATEGY_API_KEY"],
    )
    
    # 2. Load Universe
    exchange_universe = client.fetch_exchange_universe()
    pairs_df = client.fetch_pair_universe().to_pandas()
    pair_universe = PandasPairUniverse(pairs_df, exchange_universe=exchange_universe)
    
    # 3. Identify specific pairs
    pair_ids = [
        pair_universe.get_pair_by_human_description(
            [ChainId.ethereum, "uniswap-v3", "WETH", "USDC", 0.0005]
        ).pair_id
    ]
    
    # 4. Download historical candle data
    start = pd.Timestamp.utcnow() - pd.Timedelta("3d")
    end = pd.Timestamp.utcnow()
    
    clmm_df = client.fetch_clmm_liquidity_provision_candles_by_pair_ids(
        pair_ids,
        TimeBucket.d1,
        start_time=start,
        end_time=end,
    )
  6. Fetch top trading pairs with `fetch_top_pairs`

    master

    The fetch_top_pairs method scans and ranks new trading pairs for inclusion in a trading universe. It supports two primary modes of operation via the TopPairMethod enum:

    1. TopPairMethod.sorted_by_liquidity_with_filtering: Requires chain_ids, limit, and exchange_slugs. It returns the best pairs across specified exchanges.
    2. TopPairMethod.by_token_addresses: Requires chain_ids and addresses (token smart contract addresses). It returns the best pairs for those specific tokens.

    Important Notes:

    • API Status: This API is under heavy development.
    • Performance: Depending on TokenSniffer data, this may take up to 15 seconds per token.
    • Data Freshness: Results are filled asynchronously and may not reflect the most recent data due to processing delays.
    • Persistence: When storing results, use the tuple (chain id, pool address) as the persistent key.
    # Example: Get top tokens of Uniswap on Ethereum
    top_reply = client.fetch_top_pairs(
        chain_ids={ChainId.ethereum},
        exchange_slugs={"uniswap-v2", "uniswap-v3"},
        limit=10,
    )
    
    # Example: Get best trading pairs for specific Ethereum tokens
    top_reply = client.fetch_top_pairs(
        chain_ids={ChainId.ethereum},
        addresses={
            "0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9",  # COMP
            "0xc00e94Cb662C3520282E6f5717214004A7f26888"   # AAVE
        },
        method=TopPairMethod.by_token_addresses,
        limit=None,
    )
  7. Fetch Trading Pair Candles

    master

    To retrieve OHLCV candle data for specific trading pairs, use fetch_candles_by_pair_ids. This method uses a lightweight JSONL API endpoint, making it ideal for querying a small number of pairs. It is significantly more efficient than downloading entire Parquet datasets if you only need specific data.

    import datetime
    import pandas as pd
    from tradingstrategy.timebucket import TimeBucket
    
    # pair_ids must be obtained from the pair universe
    هاcandles_df = client.fetch_candles_by_pair_ids(
        pair_ids=[pair_id_1, pair_id_2],
        bucket=TimeBucket.h1,
        start_time=datetime.datetime(2024, 1, 1),
        end_time=datetime.datetime(2024, 1, 2)
    )
  8. Fetch TVL (Total Value Locked) Data

    master

    The fetch_tvl method allows you to retrieve liquidity/TVL data. You can query by a specific list of pair_ids or filter the entire exchange universe by a minimum TVL threshold using mode="min_tvl" or mode="min_tvl_low".

    from tradingstrategy.timebucket import TimeBucket
    
    # Example: Fetch TVL for specific pairs
    tvl_df = client.fetch_tvl(
        mode="pair_ids",
        bucket=TimeBucket.d1,
        pair_ids=[pair_id_1],
        start_time=start_date,
        end_time=end_date
    )
    
    # Example: Filter exchanges by minimum TVL
    tvl_filtered_df = client.fetch_tvl(
        mode="min_tvl",
        bucket=TimeBucket.d1,
        min_tvl=1_500_000,
        start_time=start_date,
        end_time=end_date
    )
  9. Manage Local Cache

    master

    The client uses a disk cache to avoid re-downloading large datasets. You can manually clear the cache using clear_caches(). If you provide a specific filename, only that file will be removed; otherwise, the entire cache for the current transport will be purged.

    # Clear everything
    client.clear_caches()
    
    # Clear a specific file
    client.clear_caches(filename="path/to/specific_data.parquet")
  10. Fetch Lending Market Candles

    master

    You can fetch lending-specific data (like variable borrow APR or supply APR) for specific reserves using fetch_lending_candles_by_reserve_id or for an entire universe of reserves using fetch_lending_candles_for_universe. The latter is optimized to load multiple reserves at once and provides a dictionary of DataFrames keyed by LendingCandleType.

    from tradingstrategy.lending import LendingCandleType
    
    # Fetch for a single reserve
    reserves_df = client.fetch_lending_candles_by_reserve_id(
        reserve_id=my_reserve_id,
        bucket=TimeBucket.h1,
        candle_type=LendingCandleType.variable_borrow_apr
    )
    
    # Fetch for a whole universe
    # result is a Dict[LendingCandleType, pd.DataFrame]
    result = client.fetch_lending_candles_for_universe(
        lending_reserve_universe=my_universe,
        bucket=TimeBucket.d1,
        candle_types=[LendingCandleType.variable_borrow_apr, LendingCandleType.supply_apr]
    )
  11. Create a live trading client with `create_live_client`

    master

    Use create_live_client to instantiate a non-interactive client suitable for production or automated scripts. This client uses standard Python logging and is designed for environments where interactive API key entry is not possible. You must provide an api_key or ensure the TRADING_STRATEGY_API_KEY environment variable is set.

    Key parameters:

    • api_key: Your Trading Strategy oracle API key (starts with secret-token:tradingstrategy-...).
    • cache_path: Directory where downloaded datasets are stored. Defaults to ~/.cache.
    • settings_path: Path to the settings file. Set to None in Docker environments to disable settings file usage.
    import os
    from tradingstrategy.client import Client
    
    # Disable the settings file. 
    # API key must be given in an environment variable.
    client = Client.create_live_client(
        settings_path=None,
        api_key=os.environ["TRADING_STRATEGY_API_KEY"],
    )