synth-crunch


Namesynth-crunch JSON
Version 0.2.2 PyPI version JSON
download
home_pagehttps://github.com/crunchdao/synth-crunch
Summarysynth-crunch - Utility package for the Synth competition on CrunchDAO!
upload_time2025-08-21 19:54:14
maintainerNone
docs_urlNone
authorEnzo CACERES
requires_python>=3.10
licenseNone
keywords crunchdao crunch synth
VCS
bugtrack_url
requirements matplotlib numpy pandas requests tqdm properscoring
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Synth on CrunchDAO

Participate to the [Synth Subnet](https://github.com/mode-network/synth-subnet) directly via the CrunchDAO Platform, making it easier to have your code enter the protocol at no cost!

- [Synth on CrunchDAO](#synth-on-crunchdao)
- [Install](#install)
- [Your first model](#your-first-model)
- [Test it locally](#test-it-locally)
  - [Running using historical data](#running-using-historical-data)
  - [Running using live data](#running-using-live-data)
  - [Visualize the simulations](#visualize-the-simulations)
  - [Score the simulations](#score-the-simulations)
- [Accessing more data (for training only)](#accessing-more-data-for-training-only)

# Install

```bash
pip install synth-crunch
```

# Your first model

You may use the following code as a baseline submission, which has been adapted from the [official Synth Subnet example](https://github.com/mode-network/synth-subnet/blob/f66ea914bd62cd4c173da98ba1061a287242dbba/synth/miner/simulations.py#L10).

```python
from typing import Any

# Import the types
from synth_crunch import SynthMiner, Asset

# Import baseline functions
from synth_crunch.baseline import simulate_crypto_price_paths, convert_prices_to_time_format


class MyMiner(SynthMiner):

    def __init__(self):
        # Initialize your state in the constructor:
        # - load your model
        # - warmup your code

        pass

    def generate_simulations(
        self,
        asset: Asset,  # can only be "BTC", "ETH", "XAU" or "SOL"
        current_price: float,
        start_time: str,
        time_increment: int,
        time_length: int,
        num_simulations: int,
    ) -> list[list[dict[str, Any]]]:
        """
        Generate simulated price paths.

        Parameters:
            asset (str): The asset to simulate.
            current_price (float): The current price of the asset to simulate.
            start_time (str): The start time of the simulation. Defaults to current time.
            time_increment (int): Time increment in seconds.
            time_length (int): Total time length in seconds.
            num_simulations (int): Number of simulation runs.

        Returns:
            list[list[dict[str, Any]]]: A simulations list that contains a list of points, defined as {"time": str, "price": float}.
        """

        if start_time == "":
            raise ValueError("Start time must be provided.")

        sigma = 0.1
        if asset == "BTC":
            sigma *= 3
        elif asset == "ETH":
            sigma *= 1.25
        elif asset == "XAU":
            sigma *= 0.5
        elif asset == "SOL":
            sigma *= 0.75

        simulations = simulate_crypto_price_paths(
            current_price=current_price,
            time_increment=time_increment,
            time_length=time_length,
            num_simulations=num_simulations,
            sigma=sigma,
        )

        predictions = convert_prices_to_time_format(
            prices=simulations.tolist(),
            start_time=start_time,
            time_increment=time_increment,
        )

        return predictions
```

# Test it locally

Your miner can test on either historical or live data.

We recommend using historical data for quick iterations because you can be scored immediately. 

When you are ready to use the brand new data, use the live data. However, you will have to wait before you can be scored.

Once you have generated your simulations, they are validated to ensure that you are ready for the network.

## Running using historical data

```python
from datetime import datetime

# Import the function
from synth_crunch import test_historical

# Run the tester
result = test_historical(
    # You must instantiate your miner.
    MyMiner(),

    # Specify which asset you want to run with: "BTC," "ETH," "XAU," or "SOL".
    "BTC",

    # Customize the start date (default to 1st of February 2024 at 02:00 PM).
    start=datetime(2024, 2, 1, 14),

    # Customize the time increment between two predictions (default to 5min).
    time_increment=300,

    # Customize the duration of a simulation; it must be a divisor of the time increment (default to 24h).
    time_length=86400,

    # Customize the number of simulations to run (default to 300).
    num_simulations=300,
)
```

> [!TIP]
> Using the same `start` and `time_increment` parameters will make subsequent execution faster because the prices will be cached in memory.

## Running using live data

```python
# Import the function
from synth_crunch import test_live

# Run the tester
result = test_live(
    # You must instantiate your miner.
    MyMiner(),

    # Specify which asset you want to run with: "BTC," "ETH," "XAU," or "SOL".
    "BTC",

    # Customize the time increment between two predictions (default to 1min).
    time_increment=60,

    # Customize the duration of a simulation; it must be a divisor of the time increment (default to 5min).
    time_length=300,

    # Customize the number of simulations to run (default to 100).
    num_simulations=100,
)
```

> [!NOTE]
> The longer your `time_length` is, the longer you will have to wait to score your simulations.

## Visualize the simulations

It's easy to plot your simulations in one line.

```python
# Import the function
from synth_crunch import visualize_simulations

visualize_simulations(
    result,

    # Show a line with the price before your simulations with up to `n * time_interval` points. Set to `False` to disable it.
    show_past=10,

    # Customize the figure size (default to (10, 6)).
    figsize=(10, 6),
)
```

The code will produce the following:

![visualization](./assets/visualization.png)

## Score the simulations

Your simulations will be scored using [Synth Subnet's scoring function](https://github.com/mode-network/synth-subnet/blob/d076dc3bcdf93256a278dfec1cbe72b0c47612f6/synth/validator/crps_calculation.py#L5).

If you run a test using live data, you will have to wait for the targets to resolve before you can score them. The function will wait by default (`time.sleep(x)`) until the time comes. If you do not want to wait, an error will be raised instead.

```python
# Import the function
from synth_crunch import score_simulations

# Score your results
scored_result = score_simulations(
    result,

    # Use sleep to wait until the targets are resolved (default to True).
    wait_until_resolved=True,
)

print("My miner score is:", scored_result.score)
print()

print("More details:")
print(scored_result.score_summary)
```

> [!WARNING]
> This will not be your score on the leaderboard. When multiple miners are scored to generate a leaderboard, [the scores are first subtracted from the lowest miner's score. Then, the prompt score is used to compute the rewards.](https://github.com/mode-network/synth-subnet/blob/d076dc3bcdf93256a278dfec1cbe72b0c47612f6/synth/validator/reward.py#L180)

# Accessing more data (for training only)

For this competition, you may use any data you wish for your training.

The library exposes a mini Python client, which allows you to easily access asset prices from [Pyth](https://pyth.network/) with up to one year at a time.

> [!IMPORTANT]  
> The Pyth data is only available for training. This is because no Internet connection is possible when running on the platform.

```python
from datetime import datetime

# Import the function
from synth_crunch import pyth

prices = pyth.get_price_history(
    # Specify which asset you want to get data of: "BTC," "ETH," "XAU," or "SOL".
    asset="BTC",

    # Start time of the data.
    from_=datetime(2024, 1, 1),

    # End time of the data (up to 1 year).
    to=datetime(2024, 1, 2),

    # Data resolution, must be one of: "minute", "2minute", "5minute", "15minute", "30minute", "hour", "2hour", "4hour", "6hour", "12hour", "day", "week", "month".
    resolution="minute",
)
```

The prices are represented using a `pandas.Series` of `float`, using `datetime` as index.

> [!WARNING]
> Pyth limits the number of data points that can be returned at once. If you are requesting a large amount of data, you may need to change the `resolution` (e.g. for a year, the smallest resolution is `"hour"`).

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/crunchdao/synth-crunch",
    "name": "synth-crunch",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.10",
    "maintainer_email": null,
    "keywords": "crunchdao, crunch, synth",
    "author": "Enzo CACERES",
    "author_email": "enzo.caceres@crunchdao.com",
    "download_url": "https://files.pythonhosted.org/packages/e3/24/d5bd2c2b83d774175bb80425d53f34e94320b92c083bf1ad30af987bad1b/synth_crunch-0.2.2.tar.gz",
    "platform": null,
    "description": "# Synth on CrunchDAO\n\nParticipate to the [Synth Subnet](https://github.com/mode-network/synth-subnet) directly via the CrunchDAO Platform, making it easier to have your code enter the protocol at no cost!\n\n- [Synth on CrunchDAO](#synth-on-crunchdao)\n- [Install](#install)\n- [Your first model](#your-first-model)\n- [Test it locally](#test-it-locally)\n  - [Running using historical data](#running-using-historical-data)\n  - [Running using live data](#running-using-live-data)\n  - [Visualize the simulations](#visualize-the-simulations)\n  - [Score the simulations](#score-the-simulations)\n- [Accessing more data (for training only)](#accessing-more-data-for-training-only)\n\n# Install\n\n```bash\npip install synth-crunch\n```\n\n# Your first model\n\nYou may use the following code as a baseline submission, which has been adapted from the [official Synth Subnet example](https://github.com/mode-network/synth-subnet/blob/f66ea914bd62cd4c173da98ba1061a287242dbba/synth/miner/simulations.py#L10).\n\n```python\nfrom typing import Any\n\n# Import the types\nfrom synth_crunch import SynthMiner, Asset\n\n# Import baseline functions\nfrom synth_crunch.baseline import simulate_crypto_price_paths, convert_prices_to_time_format\n\n\nclass MyMiner(SynthMiner):\n\n    def __init__(self):\n        # Initialize your state in the constructor:\n        # - load your model\n        # - warmup your code\n\n        pass\n\n    def generate_simulations(\n        self,\n        asset: Asset,  # can only be \"BTC\", \"ETH\", \"XAU\" or \"SOL\"\n        current_price: float,\n        start_time: str,\n        time_increment: int,\n        time_length: int,\n        num_simulations: int,\n    ) -> list[list[dict[str, Any]]]:\n        \"\"\"\n        Generate simulated price paths.\n\n        Parameters:\n            asset (str): The asset to simulate.\n            current_price (float): The current price of the asset to simulate.\n            start_time (str): The start time of the simulation. Defaults to current time.\n            time_increment (int): Time increment in seconds.\n            time_length (int): Total time length in seconds.\n            num_simulations (int): Number of simulation runs.\n\n        Returns:\n            list[list[dict[str, Any]]]: A simulations list that contains a list of points, defined as {\"time\": str, \"price\": float}.\n        \"\"\"\n\n        if start_time == \"\":\n            raise ValueError(\"Start time must be provided.\")\n\n        sigma = 0.1\n        if asset == \"BTC\":\n            sigma *= 3\n        elif asset == \"ETH\":\n            sigma *= 1.25\n        elif asset == \"XAU\":\n            sigma *= 0.5\n        elif asset == \"SOL\":\n            sigma *= 0.75\n\n        simulations = simulate_crypto_price_paths(\n            current_price=current_price,\n            time_increment=time_increment,\n            time_length=time_length,\n            num_simulations=num_simulations,\n            sigma=sigma,\n        )\n\n        predictions = convert_prices_to_time_format(\n            prices=simulations.tolist(),\n            start_time=start_time,\n            time_increment=time_increment,\n        )\n\n        return predictions\n```\n\n# Test it locally\n\nYour miner can test on either historical or live data.\n\nWe recommend using historical data for quick iterations because you can be scored immediately. \n\nWhen you are ready to use the brand new data, use the live data. However, you will have to wait before you can be scored.\n\nOnce you have generated your simulations, they are validated to ensure that you are ready for the network.\n\n## Running using historical data\n\n```python\nfrom datetime import datetime\n\n# Import the function\nfrom synth_crunch import test_historical\n\n# Run the tester\nresult = test_historical(\n    # You must instantiate your miner.\n    MyMiner(),\n\n    # Specify which asset you want to run with: \"BTC,\" \"ETH,\" \"XAU,\" or \"SOL\".\n    \"BTC\",\n\n    # Customize the start date (default to 1st of February 2024 at 02:00 PM).\n    start=datetime(2024, 2, 1, 14),\n\n    # Customize the time increment between two predictions (default to 5min).\n    time_increment=300,\n\n    # Customize the duration of a simulation; it must be a divisor of the time increment (default to 24h).\n    time_length=86400,\n\n    # Customize the number of simulations to run (default to 300).\n    num_simulations=300,\n)\n```\n\n> [!TIP]\n> Using the same `start` and `time_increment` parameters will make subsequent execution faster because the prices will be cached in memory.\n\n## Running using live data\n\n```python\n# Import the function\nfrom synth_crunch import test_live\n\n# Run the tester\nresult = test_live(\n    # You must instantiate your miner.\n    MyMiner(),\n\n    # Specify which asset you want to run with: \"BTC,\" \"ETH,\" \"XAU,\" or \"SOL\".\n    \"BTC\",\n\n    # Customize the time increment between two predictions (default to 1min).\n    time_increment=60,\n\n    # Customize the duration of a simulation; it must be a divisor of the time increment (default to 5min).\n    time_length=300,\n\n    # Customize the number of simulations to run (default to 100).\n    num_simulations=100,\n)\n```\n\n> [!NOTE]\n> The longer your `time_length` is, the longer you will have to wait to score your simulations.\n\n## Visualize the simulations\n\nIt's easy to plot your simulations in one line.\n\n```python\n# Import the function\nfrom synth_crunch import visualize_simulations\n\nvisualize_simulations(\n    result,\n\n    # Show a line with the price before your simulations with up to `n * time_interval` points. Set to `False` to disable it.\n    show_past=10,\n\n    # Customize the figure size (default to (10, 6)).\n    figsize=(10, 6),\n)\n```\n\nThe code will produce the following:\n\n![visualization](./assets/visualization.png)\n\n## Score the simulations\n\nYour simulations will be scored using [Synth Subnet's scoring function](https://github.com/mode-network/synth-subnet/blob/d076dc3bcdf93256a278dfec1cbe72b0c47612f6/synth/validator/crps_calculation.py#L5).\n\nIf you run a test using live data, you will have to wait for the targets to resolve before you can score them. The function will wait by default (`time.sleep(x)`) until the time comes. If you do not want to wait, an error will be raised instead.\n\n```python\n# Import the function\nfrom synth_crunch import score_simulations\n\n# Score your results\nscored_result = score_simulations(\n    result,\n\n    # Use sleep to wait until the targets are resolved (default to True).\n    wait_until_resolved=True,\n)\n\nprint(\"My miner score is:\", scored_result.score)\nprint()\n\nprint(\"More details:\")\nprint(scored_result.score_summary)\n```\n\n> [!WARNING]\n> This will not be your score on the leaderboard. When multiple miners are scored to generate a leaderboard, [the scores are first subtracted from the lowest miner's score. Then, the prompt score is used to compute the rewards.](https://github.com/mode-network/synth-subnet/blob/d076dc3bcdf93256a278dfec1cbe72b0c47612f6/synth/validator/reward.py#L180)\n\n# Accessing more data (for training only)\n\nFor this competition, you may use any data you wish for your training.\n\nThe library exposes a mini Python client, which allows you to easily access asset prices from [Pyth](https://pyth.network/) with up to one year at a time.\n\n> [!IMPORTANT]  \n> The Pyth data is only available for training. This is because no Internet connection is possible when running on the platform.\n\n```python\nfrom datetime import datetime\n\n# Import the function\nfrom synth_crunch import pyth\n\nprices = pyth.get_price_history(\n    # Specify which asset you want to get data of: \"BTC,\" \"ETH,\" \"XAU,\" or \"SOL\".\n    asset=\"BTC\",\n\n    # Start time of the data.\n    from_=datetime(2024, 1, 1),\n\n    # End time of the data (up to 1 year).\n    to=datetime(2024, 1, 2),\n\n    # Data resolution, must be one of: \"minute\", \"2minute\", \"5minute\", \"15minute\", \"30minute\", \"hour\", \"2hour\", \"4hour\", \"6hour\", \"12hour\", \"day\", \"week\", \"month\".\n    resolution=\"minute\",\n)\n```\n\nThe prices are represented using a `pandas.Series` of `float`, using `datetime` as index.\n\n> [!WARNING]\n> Pyth limits the number of data points that can be returned at once. If you are requesting a large amount of data, you may need to change the `resolution` (e.g. for a year, the smallest resolution is `\"hour\"`).\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "synth-crunch - Utility package for the Synth competition on CrunchDAO!",
    "version": "0.2.2",
    "project_urls": {
        "Homepage": "https://github.com/crunchdao/synth-crunch"
    },
    "split_keywords": [
        "crunchdao",
        " crunch",
        " synth"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "a35be4683f630c4a93205ecbe2c3c2ff33651aa376d2344a1f5067390e9c18a3",
                "md5": "1da3b858f73df170ebc8c6e9535147a7",
                "sha256": "ff87e1244b769ffbc872eaca6603e7c08a62bf4b756e5867f8d036fc3045c5df"
            },
            "downloads": -1,
            "filename": "synth_crunch-0.2.2-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "1da3b858f73df170ebc8c6e9535147a7",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.10",
            "size": 13815,
            "upload_time": "2025-08-21T19:54:13",
            "upload_time_iso_8601": "2025-08-21T19:54:13.164810Z",
            "url": "https://files.pythonhosted.org/packages/a3/5b/e4683f630c4a93205ecbe2c3c2ff33651aa376d2344a1f5067390e9c18a3/synth_crunch-0.2.2-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "e324d5bd2c2b83d774175bb80425d53f34e94320b92c083bf1ad30af987bad1b",
                "md5": "88c82df621aef3fed7d1c8f3095c23ca",
                "sha256": "1226a8764a399613788b7b7574b80c53676037d8489ecb04c9b6ace21d630c53"
            },
            "downloads": -1,
            "filename": "synth_crunch-0.2.2.tar.gz",
            "has_sig": false,
            "md5_digest": "88c82df621aef3fed7d1c8f3095c23ca",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.10",
            "size": 16234,
            "upload_time": "2025-08-21T19:54:14",
            "upload_time_iso_8601": "2025-08-21T19:54:14.188183Z",
            "url": "https://files.pythonhosted.org/packages/e3/24/d5bd2c2b83d774175bb80425d53f34e94320b92c083bf1ad30af987bad1b/synth_crunch-0.2.2.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-08-21 19:54:14",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "crunchdao",
    "github_project": "synth-crunch",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "requirements": [
        {
            "name": "matplotlib",
            "specs": []
        },
        {
            "name": "numpy",
            "specs": []
        },
        {
            "name": "pandas",
            "specs": []
        },
        {
            "name": "requests",
            "specs": []
        },
        {
            "name": "tqdm",
            "specs": []
        },
        {
            "name": "properscoring",
            "specs": []
        }
    ],
    "lcname": "synth-crunch"
}
        
Elapsed time: 2.24493s