tradingstrategy-ai / trade-executor

A Python framework for managing positions and trades in DeFi
https://tradingstrategy.ai
Other
106 stars 29 forks source link

Improve chart endpoint performance #690

Closed kenkunz closed 7 months ago

kenkunz commented 11 months ago

Goal

As an investor or strategy developer, I want strategy charts to load quickly while still displaying current data, so that I can efficiently browse and analyze strategies.

Background

The chart endpoint is relatively slow (due to chart data being computed on-the fly). For example, the following request generally takes about 5 seconds:

curl "http://enzyme-polygon-matic-usdc.tradingstrategy.ai/chart?type=compounding_realised_profitability&source=live_trading"

This could be optimized in a variety of ways. One option would be simply to add Etag headers (and appropriate Cloudflare configuration) to enable clients and proxies to serve cached data.

Acceptance Criteria

  1. Requests for chart data for any strategy (and for any chart param options) are responded to in less than 1 second.
  2. When updated data is available, stale data may be served for a limited time until the updated data is available to be served
    • this is preferred to having a long wait time for the fully fresh data
    • stale data should only be served for up to 1 minute past its expiration time
    • consider using stale-while-revalidate directive or a similar strategy (serve stale data while cache is being asynchronously refreshed)
  3. It is acceptable if the first time loading the chart endpoint (for a given combination of params) is slow. The client (e.g., frontend) should provide appropriate loading feedback.
kenkunz commented 11 months ago

Per @miohtama via discord thread:

The easiest is to cache these on trade-executor's internal RuntimeState that's just in-memory dictionary so we should be probably be good without any frontend changes HOWEVER the first load may be still slow, so we still might need to create good skeleton loaders

long term we should be able to generate these all upfront, but there is a trade off, as if we start to generate them during the strategy cycle it will slow down other things, so optimally it should be 1) "fast enough" 2) generated only on request

AlexTheLion123 commented 9 months ago

@kenkunz The performance chart is now part of RunState

https://github.com/tradingstrategy-ai/trade-executor/blob/91ade3077edaa897e3ffa3bdf39e463e64df6e10/tradeexecutor/statistics/in_memory_statistics.py#L62

It would be run_state.summary_statistics.performance_chart_90_days

kenkunz commented 9 months ago

@AlexTheLion123 yes, frontend currently uses performance_chart_90_days to generate the chart thumbnails on the strategy index page.

The data semantics of performance_chart_90_days are different from the chart endpoint:

performance_chart_90_days chart endpoint
time window 90 days full history
time bucket daily variable, sub-hourly
(based on re-calculation events)

…so performance_chart_90_days is useful for the index view thumbnails, but less useful on the overview or performance pages where we want the user to be able to zoom in to see more fine-grained changes in data or zoom out / scroll back to see longer history.

I'm hesitant to add a lot of additional data to the metadata endpoint (runtime state) since we want that to remain performant for the index page.

One option to consider on frontend is to use performance_chart_90_days on the strategy overview page for initial load, then load the chart endpoint in the background and swap in the more complete data when it's done loading. As long as the user doesn't toggle the time bucket picker before the chart fetch completes, this should be transparent. If the user does toggle before the data is available, we can show a loading indicator.

miohtama commented 7 months ago

@miohtama We should have a fix for this tonight to address the API endpoint latency issue (is caused by a JSON deserialisation and disk read).