-
Notifications
You must be signed in to change notification settings - Fork 118
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' into docs-basic-agent
- Loading branch information
Showing
6 changed files
with
510 additions
and
124 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,178 @@ | ||
package pricepred | ||
|
||
import ( | ||
"bytes" | ||
"context" | ||
"encoding/json" | ||
"fmt" | ||
"io" | ||
"net/http" | ||
"net/url" | ||
"time" | ||
) | ||
|
||
type client struct { | ||
c *http.Client | ||
predictURL string | ||
backtestingURL string | ||
} | ||
|
||
func newClient(c *http.Client, baseURL *url.URL) *client { | ||
predictURL := baseURL.JoinPath("/api/task/inference/solve") | ||
backtestingURL := baseURL.JoinPath("/api/task/backtesting/solve") | ||
|
||
return &client{ | ||
c: c, | ||
predictURL: predictURL.String(), | ||
backtestingURL: backtestingURL.String(), | ||
} | ||
} | ||
|
||
type RequestSolverInput struct { | ||
Tokens []string `json:"tokens"` | ||
TargetDate string `json:"target_date"` | ||
AdversaryMode bool `json:"adversaryMode"` | ||
} | ||
|
||
type ResponseSolverReceipt struct { | ||
BloomFilter []byte `json:"bloomFilter"` | ||
CountItems int `json:"countItems"` | ||
} | ||
|
||
type PredictRequest struct { | ||
SolverInput RequestSolverInput `json:"solverInput"` | ||
FalsePositiveRate float64 `json:"falsePositiveRate"` | ||
} | ||
|
||
type PredictResponse struct { | ||
SolverOutput map[string]float64 `json:"solverOutput"` | ||
SolverReceipt ResponseSolverReceipt `json:"solverReceipt"` | ||
} | ||
|
||
func (c *client) Predict(ctx context.Context, req PredictRequest) (PredictResponse, error) { | ||
reqCtx, cancel := context.WithTimeout(ctx, 3*time.Second) | ||
defer cancel() | ||
|
||
reqBody, err := json.Marshal(req) | ||
if err != nil { | ||
return PredictResponse{}, err | ||
} | ||
|
||
httpReq, err := http.NewRequestWithContext(reqCtx, "POST", c.predictURL, bytes.NewReader(reqBody)) | ||
if err != nil { | ||
return PredictResponse{}, err | ||
} | ||
|
||
httpReq.Header.Set("Accept", "application/json") | ||
httpReq.Header.Set("Content-Type", "application/json") | ||
|
||
res, err := c.c.Do(httpReq) | ||
if err != nil { | ||
return PredictResponse{}, err | ||
} | ||
defer res.Body.Close() | ||
response, err := io.ReadAll(res.Body) | ||
if err != nil { | ||
return PredictResponse{}, err | ||
} | ||
|
||
if res.StatusCode != http.StatusOK { | ||
return PredictResponse{}, fmt.Errorf("unexpected status code: %d. Server returned error: %s", res.StatusCode, response) | ||
} | ||
|
||
var resResp PredictResponse | ||
err = json.Unmarshal(response, &resResp) | ||
if err != nil { | ||
return PredictResponse{}, err | ||
} | ||
|
||
return resResp, nil | ||
} | ||
|
||
type BacktestingRequest struct { | ||
SolverInput RequestSolverInput `json:"solverInput"` | ||
FalsePositiveRate float64 `json:"falsePositiveRate"` | ||
} | ||
|
||
type BacktestingMetrics struct { | ||
Count float64 `json:"count"` | ||
Mape float64 `json:"mape"` | ||
Rmse float64 `json:"rmse"` | ||
R2 float64 `json:"r2"` | ||
MaxError float64 `json:"max_error"` | ||
Dae float64 `json:"dae"` | ||
Mae float64 `json:"mae"` | ||
Confidence float64 `json:"confidence"` | ||
Pct1 float64 `json:"pct1"` | ||
Pct5 float64 `json:"pct5"` | ||
Pct10 float64 `json:"pct10"` | ||
Pct15 float64 `json:"pct15"` | ||
Pct20 float64 `json:"pct20"` | ||
Pct25 float64 `json:"pct25"` | ||
Pct50 float64 `json:"pct50"` | ||
P0 float64 `json:"p0"` | ||
P5 float64 `json:"p5"` | ||
P10 float64 `json:"p10"` | ||
P15 float64 `json:"p15"` | ||
P20 float64 `json:"p20"` | ||
P25 float64 `json:"p25"` | ||
P50 float64 `json:"p50"` | ||
P75 float64 `json:"p75"` | ||
P95 float64 `json:"p95"` | ||
P100 float64 `json:"p100"` | ||
} | ||
|
||
type BacktestingToken struct { | ||
Metrics BacktestingMetrics `json:"metrics"` | ||
} | ||
|
||
type BacktestingSolverOutput struct { | ||
Metrics BacktestingMetrics `json:"metrics"` | ||
Tokens map[string]BacktestingToken `json:"tokens"` | ||
} | ||
|
||
type BacktestingResponse struct { | ||
SolverOutput BacktestingSolverOutput `json:"solverOutput"` | ||
SolverReceipt ResponseSolverReceipt `json:"solverReceipt"` | ||
} | ||
|
||
func (c *client) Backtesting(ctx context.Context, req BacktestingRequest) (BacktestingResponse, error) { | ||
reqCtx, cancel := context.WithTimeout(ctx, 10*time.Second) | ||
defer cancel() | ||
|
||
reqBody, err := json.Marshal(req) | ||
if err != nil { | ||
return BacktestingResponse{}, err | ||
} | ||
|
||
httpReq, err := http.NewRequestWithContext(reqCtx, "POST", c.backtestingURL, bytes.NewReader(reqBody)) | ||
if err != nil { | ||
return BacktestingResponse{}, err | ||
} | ||
|
||
httpReq.Header.Set("Accept", "application/json") | ||
httpReq.Header.Set("Content-Type", "application/json") | ||
|
||
res, err := c.c.Do(httpReq) | ||
if err != nil { | ||
return BacktestingResponse{}, err | ||
} | ||
defer res.Body.Close() | ||
|
||
response, err := io.ReadAll(res.Body) | ||
if err != nil { | ||
return BacktestingResponse{}, err | ||
} | ||
|
||
if res.StatusCode != http.StatusOK { | ||
return BacktestingResponse{}, fmt.Errorf("unexpected status code: %d. Server returned error: %s", res.StatusCode, response) | ||
} | ||
|
||
var resResp BacktestingResponse | ||
err = json.Unmarshal(response, &resResp) | ||
if err != nil { | ||
return BacktestingResponse{}, err | ||
} | ||
|
||
return resResp, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
package pricepred | ||
|
||
import ( | ||
"context" | ||
"net/http" | ||
"net/url" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestPredict(t *testing.T) { | ||
t.Skip("this test relies on external HTTP call") | ||
|
||
c := newClient(http.DefaultClient, &url.URL{ | ||
Scheme: "https", | ||
Host: "tpc.devnet.wardenprotocol.org", | ||
}) | ||
|
||
ctx := context.Background() | ||
res, err := c.Predict(ctx, PredictRequest{ | ||
SolverInput: RequestSolverInput{ | ||
Tokens: []string{"bitcoin", "tether", "uniswap"}, | ||
TargetDate: "2022-01-01", | ||
AdversaryMode: false, | ||
}, | ||
FalsePositiveRate: 0.01, | ||
}) | ||
require.NoError(t, err) | ||
require.Len(t, res.SolverOutput, 3) | ||
|
||
for token, pred := range res.SolverOutput { | ||
require.NotZero(t, pred, "prediction for %t is zero", token) | ||
} | ||
} | ||
|
||
func TestBacktesting(t *testing.T) { | ||
t.Skip("this test relies on external HTTP call") | ||
|
||
c := newClient(http.DefaultClient, &url.URL{ | ||
Scheme: "https", | ||
Host: "tpc.devnet.wardenprotocol.org", | ||
}) | ||
|
||
ctx := context.Background() | ||
res, err := c.Backtesting(ctx, BacktestingRequest{ | ||
SolverInput: RequestSolverInput{ | ||
Tokens: []string{"bitcoin", "tether", "uniswap"}, | ||
TargetDate: "2025-01-28", | ||
AdversaryMode: false, | ||
}, | ||
FalsePositiveRate: 0.01, | ||
}) | ||
require.NoError(t, err) | ||
|
||
require.NotZero(t, res.SolverOutput.Metrics) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.