From 9ed2678d1d74a8bcd24f4d7e9315c17a6b968a77 Mon Sep 17 00:00:00 2001 From: xnerhu Date: Fri, 1 Aug 2025 16:09:21 +0200 Subject: [PATCH 1/5] xd --- .github/workflows/cd.yaml | 24 +- BUILD.bazed | 4 +- Cargo.lock | 52 +- core/backtest.rs | 20 +- core/timeframe.rs | 18 + examples/python/main.py | 16 +- lib/__init__.py | 2 +- lib/client.py | 237 ++++++- lib/proto/BUILD.bazed | 7 + lib/proto/__init__.py | 2 + lib/proto/ohlcv.proto | 43 ++ lib/proto/ohlcv_grpc_pb.d.ts | 43 ++ lib/proto/ohlcv_grpc_pb.js | 46 ++ lib/proto/ohlcv_pb.d.ts | 157 +++++ lib/proto/ohlcv_pb.js | 1219 ++++++++++++++++++++++++++++++++++ lib/proto/ohlcv_pb2.py | 46 ++ lib/proto/ohlcv_pb2.pyi | 67 ++ lib/proto/ohlcv_pb2_grpc.py | 97 +++ 18 files changed, 2032 insertions(+), 68 deletions(-) create mode 100644 lib/proto/BUILD.bazed create mode 100644 lib/proto/__init__.py create mode 100644 lib/proto/ohlcv.proto create mode 100644 lib/proto/ohlcv_grpc_pb.d.ts create mode 100644 lib/proto/ohlcv_grpc_pb.js create mode 100644 lib/proto/ohlcv_pb.d.ts create mode 100644 lib/proto/ohlcv_pb.js create mode 100644 lib/proto/ohlcv_pb2.py create mode 100644 lib/proto/ohlcv_pb2.pyi create mode 100644 lib/proto/ohlcv_pb2_grpc.py diff --git a/.github/workflows/cd.yaml b/.github/workflows/cd.yaml index 7d1a2c8..c57b0df 100644 --- a/.github/workflows/cd.yaml +++ b/.github/workflows/cd.yaml @@ -1,18 +1,18 @@ name: CD -# on: -# workflow_dispatch: -# inputs: -# target: -# description: "Triplet to build (linux-x64-gnu / win32-x64-msvc)" -# required: false -# type: string - on: - pull_request: - push: - branches: - - master + workflow_dispatch: + inputs: + target: + description: "Triplet to build (linux-x64-gnu / win32-x64-msvc)" + required: false + type: string + +# on: +# pull_request: +# push: +# branches: +# - master # workflow_run: # workflows: ["CI"] diff --git a/BUILD.bazed b/BUILD.bazed index 5feee6e..be39bcc 100644 --- a/BUILD.bazed +++ b/BUILD.bazed @@ -149,8 +149,8 @@ setup( "requests", "tqdm", "plotly", - "grpcio==1.70.0", - "protobuf==5.29.1", + "grpcio==1.74.0", + "protobuf==6.31.1", ], # platforms=["win_amd64"], ) diff --git a/Cargo.lock b/Cargo.lock index a9f9de8..6ce5c86 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1728,26 +1728,6 @@ dependencies = [ "syn 2.0.98", ] -[[package]] -name = "pyo3-stub-gen" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e2906d67f2fa9b6079665a1d097c25530f54a8a6a40da5544370786f0adb523" -dependencies = [ - "anyhow", - "chrono", - "inventory", - "itertools 0.13.0", - "log", - "maplit", - "num-complex", - "numpy", - "pyo3", - "pyo3-stub-gen-derive 0.6.2", - "serde", - "toml", -] - [[package]] name = "pyo3-stub-gen" version = "0.7.0" @@ -1763,22 +1743,11 @@ dependencies = [ "num-complex", "numpy", "pyo3", - "pyo3-stub-gen-derive 0.7.0", + "pyo3-stub-gen-derive", "serde", "toml", ] -[[package]] -name = "pyo3-stub-gen-derive" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea3f50b3dca9a392772e45ed6db1066773c74d2be00399f46ab53cbab67a36f9" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.98", -] - [[package]] name = "pyo3-stub-gen-derive" version = "0.7.0" @@ -1799,10 +1768,6 @@ dependencies = [ "cc", ] -[[package]] -name = "qpace" -version = "0.0.1-dev.1" - [[package]] name = "qpace_core" version = "0.2.6" @@ -1825,8 +1790,8 @@ dependencies = [ "pyo3", "pyo3-build-config", "pyo3-ffi", - "pyo3-stub-gen 0.7.0", - "pyo3-stub-gen-derive 0.7.0", + "pyo3-stub-gen", + "pyo3-stub-gen-derive", "serde", "serde_json", "textplots", @@ -1834,17 +1799,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "qpace_playground_lib" -version = "0.0.1" -dependencies = [ - "pyo3", - "pyo3-ffi", - "pyo3-stub-gen 0.6.2", - "pyo3-stub-gen-derive 0.6.2", - "qpace_core", -] - [[package]] name = "quote" version = "1.0.38" diff --git a/core/backtest.rs b/core/backtest.rs index 1f6fef0..98107da 100644 --- a/core/backtest.rs +++ b/core/backtest.rs @@ -411,8 +411,18 @@ impl Backtest { return trade; } + // @TODO + // pub fn maybe_reset_equity_pct(&mut self) { + // if self.position_size() == 0.0 { + // self.prev_equity_pct = 0.0; + // } + // } + pub fn compute_equity_pct(&mut self, equity_pct: f64) -> Option { let ctx = self.ctx.borrow(); + // if self.bar_index() == 21454 || self.bar_index() == 21293 { + // println!("[{} -> compute_equity_pct]: equity(): {:?} | equity_pct: {:?} | prev_equity_pct: {:?} ", self.bar_index(), self.equity(), equity_pct, self.prev_equity_pct); + // } if self.equity() > 0.0 { if !equity_pct.compare(self.prev_equity_pct) { // if true { @@ -429,7 +439,7 @@ impl Backtest { let order_size = round_contracts(base_order_size, ctx.sym().min_qty(), ctx.sym().qty_scale()); - // if self.config.debug { + // if self.bar_index() == 21454 || self.bar_index() == 21293 { // println!("[{} -> compute_equity_pct]: equity_pct: {:?} | prev_equity_pct: {:?} | base_order_size: {:?} | order_size: {:?} | min_qty: {:?} | price_scale: {:?}", self.bar_index(), equity_pct, self.prev_equity_pct, base_order_size, order_size, ctx.sym().min_qty(), ctx.sym().price_scale()); // } @@ -656,10 +666,16 @@ impl Backtest { #[inline] pub fn signal(&mut self, signal: Signal) { + // if self.config.debug { + // println!("[{} ->raw signal]: {:?}", self.bar_index(), &signal); + // } let order: Option = match signal.kind() { SignalKind::EquityPct(pct) => self.compute_equity_pct(*pct), SignalKind::Size(size) => Some(OrderConfig::new(*size, None)), - SignalKind::CloseAll() => Some(OrderConfig::new(-self.position_size, None)), + SignalKind::CloseAll() => { + self.prev_equity_pct = 0.0; + Some(OrderConfig::new(-self.position_size, None)) + } _ => None, }; if self.config.debug { diff --git a/core/timeframe.rs b/core/timeframe.rs index 9981093..1adf639 100644 --- a/core/timeframe.rs +++ b/core/timeframe.rs @@ -220,4 +220,22 @@ impl Timeframe { pub fn unknown(&self) -> bool { matches!(self, Timeframe::Unknown()) } + + // const qpTimeframeToTradingView = ( + // timeframe: qp.Timeframe, + // ): TradingViewTimeframe => { + // if (timeframe.minutes) { + // return `${timeframe.minutes}` as TradingViewTimeframe; + // } + // if (timeframe.hours) { + // return `${timeframe.hours * 60}` as TradingViewTimeframe; + // } + // return timeframe.toString() as TradingViewTimeframe; + // }; + // #[inline] + // pub fn to_tradingview() -> String { + // match self { + + // } + // } } diff --git a/examples/python/main.py b/examples/python/main.py index 7dee572..9cccb73 100644 --- a/examples/python/main.py +++ b/examples/python/main.py @@ -1,11 +1,25 @@ import os +import sys import numpy as np import pandas as pd import qpace as qp import qpace_suite as qp_suite - +import grpc +from time import perf_counter if __name__ == "__main__": + client = qp.Client( + api_key="sk_73cc632b-b337-42a9-9e2c-5275b76873f3", + api_base="http://127.0.0.1:3000/v1", + grpc_api_base="127.0.0.1:3001", + grpc_credentials=False, + ) + sym = client.sym.get("BITSTAMP:BTCUSD") + start_time = perf_counter() + ohlcv = client.ohlcv.get(sym, qp.Timeframe.Minutes(15), limit=2048) + print(f"Time taken: {perf_counter() - start_time:.2f} seconds") + print(ohlcv[0], ohlcv[-1]) + sys.exit() ohlcv_path = os.path.join(os.path.dirname(__file__), "../assets/btc_12h.csv") ohlcv = qp.Ohlcv.read_csv(ohlcv_path) ohlcv.timeframe = qp.Timeframe.Days(1) diff --git a/lib/__init__.py b/lib/__init__.py index ff3d5e3..6b34420 100644 --- a/lib/__init__.py +++ b/lib/__init__.py @@ -1,7 +1,7 @@ from qpace_core import * -from lib.client import * import lib.ta as ta +from lib.client import Client from lib.plot import plot, Line, BarPane, Pane __version__ = "__BAZED::QPACE_VERSION__" diff --git a/lib/client.py b/lib/client.py index 93209ba..1222d9b 100644 --- a/lib/client.py +++ b/lib/client.py @@ -1,5 +1,240 @@ +from datetime import datetime, timezone +import sys +import grpc +from typing import Literal, Optional, Union import qpace_core as qp +import json +import requests +from tqdm import tqdm +from datetime import timezone +import requests +from lib.proto.ohlcv_pb2_grpc import OhlcvApiStub as OhlcvApiClient +import lib.proto.ohlcv_pb2 as ohlcv_api +from google.protobuf import timestamp_pb2 + +# DEFAULT_REST_ENDPOINT = "http://0.0.0.0:3000/v1" +# DEFAULT_GRPC_ENDPOINT = "0.0.0.0:3001" + +DEFAULT_REST_ENDPOINT = "https://api.qpace.com" +DEFAULT_GRPC_ENDPOINT = "grpc.qpace.com" + + +def proto_to_ohlcv_bar(proto: ohlcv_api.OhlcvBar) -> qp.OhlcvBar: + open_time = proto.open_time.ToDatetime(tzinfo=timezone.utc) + close_time = proto.close_time.ToDatetime(tzinfo=timezone.utc) + return qp.OhlcvBar( + open_time=open_time, + close_time=close_time, + open=proto.open, + high=proto.high, + low=proto.low, + close=proto.close, + volume=proto.volume, + ) + + +class SymClient: + def __init__(self, client: "Client"): + self.client = client + + def get( + self, + pat: Optional[str] = None, + timeframe: Optional[Union[qp.Timeframe, str]] = None, + id: Optional[str] = None, + ticker_id: Optional[str] = None, + **kwargs, + ) -> qp.Sym: + syms = self.list( + pat=pat, + timeframe=timeframe, + id=id, + ticker_id=ticker_id, + limit=1, + ) + if len(syms) == 0: + raise Exception(f"Symbol not found") + return syms[0] + + def list( + self, + pat: Optional[str] = None, + timeframe: Optional[Union[qp.Timeframe, str]] = None, + id: Optional[str] = None, + ticker_id: Optional[str] = None, + limit: Optional[int] = None, + offset: Optional[int] = None, + **kwargs, + ) -> list[qp.Sym]: + if timeframe is not None: + timeframe = str(timeframe) + if pat is not None: + id = pat + ticker_id = pat + res = self.client.http.get( + f"{self.client.api_base}/symbols", + params={ + "id_pat": id, + "ticker_id_pat": ticker_id, + "limit": limit, + "offset": offset, + "timeframe": timeframe, + }, + ) + if not res.ok: + raise Exception(f"Error: {res.status_code} {res.reason} {res.text}") + res = res.json() + return [qp.Sym.from_dict(sym) for sym in res["symbols"]] + + +class OhlcvClient: + def __init__(self, client: "Client"): + self.client = client + self._ohlcv_api_client = OhlcvApiClient(self.client.grpc_channel) + + def get( + self, + sym: Union[Optional[str], qp.Sym], + timeframe: Union[qp.Timeframe, str], + limit: Optional[int] = None, + offset: Optional[int] = None, + order: Optional[Union[Literal["asc"], Literal["desc"]]] = None, + start_open_time: Optional[datetime] = None, + end_open_time: Optional[datetime] = None, + start_close_time: Optional[datetime] = None, + end_close_time: Optional[datetime] = None, + pb: bool = False, + **kwargs, + ) -> qp.Ohlcv: + if not isinstance(sym, qp.Sym): + sym = self.client.sym.get(sym) + if sym.id is None: + raise Exception(f"Symbol has no id") + if not isinstance(timeframe, qp.Timeframe): + timeframe = qp.Timeframe.from_str(timeframe) + if offset is None: + offset = 0 + _pb: Optional[tqdm] = None + _bars: list[ohlcv_api.OhlcvBar] = [] + + # _start_time: Optional[timestamp_pb2.Timestamp] = None + # _end_time: Optional[timestamp_pb2.Timestamp] = None + # if start_time is not None: + # _start_time = timestamp_pb2.Timestamp() + # _start_time.FromDatetime(start_time) + # if end_time is not None: + # _end_time = timestamp_pb2.Timestamp() + # _end_time.FromDatetime(end_time) + _start_open_time: Optional[timestamp_pb2.Timestamp] = None + _end_open_time: Optional[timestamp_pb2.Timestamp] = None + _start_close_time: Optional[timestamp_pb2.Timestamp] = None + _end_close_time: Optional[timestamp_pb2.Timestamp] = None + if start_open_time is not None: + _start_open_time = timestamp_pb2.Timestamp() + _start_open_time.FromDatetime(start_open_time) + if end_open_time is not None: + _end_open_time = timestamp_pb2.Timestamp() + _end_open_time.FromDatetime(end_open_time) + if start_close_time is not None: + _start_close_time = timestamp_pb2.Timestamp() + _start_close_time.FromDatetime(start_close_time) + if end_close_time is not None: + _end_close_time = timestamp_pb2.Timestamp() + _end_close_time.FromDatetime(end_close_time) + + _order = None + if order == "asc": + _order = ohlcv_api.Order.ASC + elif order == "desc": + _order = ohlcv_api.Order.DESC + + while True: + req = ohlcv_api.GetRequest( + sym_id=sym.id, + timeframe=str(timeframe), + limit=limit, + offset=offset, + order=_order, + start_open_time=_start_open_time, + end_open_time=_end_open_time, + start_close_time=_start_close_time, + end_close_time=_end_close_time, + ) + res: ohlcv_api.GetResponse = self._ohlcv_api_client.Get( + req, metadata=self.client._create_grpc_metadata() + ) + bars = [proto_to_ohlcv_bar(proto) for proto in res.bars] + remaining: int = res.remaining + _bars.extend(bars) + offset += len(bars) + if remaining == 0 or limit is not None: + break + if pb: + if _pb is None: + _pb = tqdm( + total=remaining + len(_bars), + desc=f"Loading OHLCV for {sym.id} {str(timeframe)}", + mininterval=1.0, + ) + _pb.update(len(bars)) + + ohlcv = qp.Ohlcv.from_bars(_bars) + ohlcv.timeframe = timeframe + + return ohlcv class Client: - pass + def __init__( + self, + api_key: str, + api_base: Optional[str] = None, + grpc_api_base: Optional[str] = None, + grpc_credentials: Optional[grpc.ChannelCredentials] = None, + ): + from . import __version__, __core__version__ + + self.client_info = {} + self.client_info["qpaceVersion"] = __version__ + self.client_info["qpaceCoreVersion"] = __core__version__ + + self.api_key = api_key + self.api_base = api_base or DEFAULT_REST_ENDPOINT + self.grpc_api_base = grpc_api_base or DEFAULT_GRPC_ENDPOINT + + self.http = requests.Session() + self.http.headers.update({"Content-Type": "application/json"}) + self.http.headers.update({"x-api-key": self.api_key}) + self.http.headers.update({"x-info": json.dumps(self.client_info)}) + self.http.headers.update({"Accept": "application/json"}) + + grpc_options = [ + ("grpc.max_receive_message_length", -1), + ("grpc.max_send_message_length", -1), + ] + grpc_secure = grpc_credentials != False + if grpc_secure and grpc_credentials is None: + grpc_credentials = grpc.ssl_channel_credentials() + if grpc_secure: + self.grpc_channel = grpc.secure_channel( + self.grpc_api_base, + grpc_credentials, + options=grpc_options, + ) + else: + self.grpc_channel = grpc.insecure_channel( + self.grpc_api_base, + options=grpc_options, + ) + self._grpc_metadata = None + + self.sym = SymClient(self) + self.ohlcv = OhlcvClient(self) + + def _create_grpc_metadata(self) -> list[tuple[str, str]]: + if self._grpc_metadata is None: + metadata = {} + metadata["x-api-key"] = self.api_key + metadata["x-info"] = json.dumps(self.client_info) + self._grpc_metadata = metadata + return self._grpc_metadata.items() diff --git a/lib/proto/BUILD.bazed b/lib/proto/BUILD.bazed new file mode 100644 index 0000000..f527e19 --- /dev/null +++ b/lib/proto/BUILD.bazed @@ -0,0 +1,7 @@ +fileSet("py", { + srcs: [glob("**/*.py")], +}); + +fileSet("ts", { + srcs: [glob("*.{ts,js}")], +}); diff --git a/lib/proto/__init__.py b/lib/proto/__init__.py new file mode 100644 index 0000000..63e5883 --- /dev/null +++ b/lib/proto/__init__.py @@ -0,0 +1,2 @@ +from . import ohlcv_pb2 +from . import ohlcv_pb2_grpc diff --git a/lib/proto/ohlcv.proto b/lib/proto/ohlcv.proto new file mode 100644 index 0000000..e519d44 --- /dev/null +++ b/lib/proto/ohlcv.proto @@ -0,0 +1,43 @@ +syntax = "proto3"; + +import "google/protobuf/timestamp.proto"; +import "google/protobuf/empty.proto"; + +package ohlcv; + +service OhlcvApi { + rpc Get(GetRequest) returns (GetResponse); +} + +message GetRequest { + string sym_id = 1; + string timeframe = 2; + optional uint32 limit = 3; + optional uint32 offset = 4; + optional Order order = 5; + optional google.protobuf.Timestamp start_open_time = 6; // >= + optional google.protobuf.Timestamp end_open_time = 7; // <= + optional google.protobuf.Timestamp start_close_time = 8; // >= + optional google.protobuf.Timestamp end_close_time = 9; // <= +} + +message GetResponse { + repeated OhlcvBar bars = 1; + optional uint32 total = 2; // total number of bars available for that symbol and timeframe + optional uint32 remaining = 3; // number of bars remaining to be fetched +} + +message OhlcvBar { + google.protobuf.Timestamp open_time = 1; + google.protobuf.Timestamp close_time = 2; + double open = 3; + double high = 4; + double low = 5; + double close = 6; + double volume = 7; +} + +enum Order { + ASC = 0; + DESC = 1; +} diff --git a/lib/proto/ohlcv_grpc_pb.d.ts b/lib/proto/ohlcv_grpc_pb.d.ts new file mode 100644 index 0000000..e383881 --- /dev/null +++ b/lib/proto/ohlcv_grpc_pb.d.ts @@ -0,0 +1,43 @@ +// package: ohlcv +// file: ohlcv.proto + +/* tslint:disable */ +/* eslint-disable */ + +import * as grpc from "@grpc/grpc-js"; +import * as ohlcv_pb from "./ohlcv_pb"; +import * as google_protobuf_timestamp_pb from "google-protobuf/google/protobuf/timestamp_pb"; +import * as google_protobuf_empty_pb from "google-protobuf/google/protobuf/empty_pb"; + +interface IOhlcvApiService extends grpc.ServiceDefinition { + get: IOhlcvApiService_IGet; +} + +interface IOhlcvApiService_IGet extends grpc.MethodDefinition { + path: "/ohlcv.OhlcvApi/Get"; + requestStream: false; + responseStream: false; + requestSerialize: grpc.serialize; + requestDeserialize: grpc.deserialize; + responseSerialize: grpc.serialize; + responseDeserialize: grpc.deserialize; +} + +export const OhlcvApiService: IOhlcvApiService; + +export interface IOhlcvApiServer extends grpc.UntypedServiceImplementation { + get: grpc.handleUnaryCall; +} + +export interface IOhlcvApiClient { + get(request: ohlcv_pb.GetRequest, callback: (error: grpc.ServiceError | null, response: ohlcv_pb.GetResponse) => void): grpc.ClientUnaryCall; + get(request: ohlcv_pb.GetRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: ohlcv_pb.GetResponse) => void): grpc.ClientUnaryCall; + get(request: ohlcv_pb.GetRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: ohlcv_pb.GetResponse) => void): grpc.ClientUnaryCall; +} + +export class OhlcvApiClient extends grpc.Client implements IOhlcvApiClient { + constructor(address: string, credentials: grpc.ChannelCredentials, options?: Partial); + public get(request: ohlcv_pb.GetRequest, callback: (error: grpc.ServiceError | null, response: ohlcv_pb.GetResponse) => void): grpc.ClientUnaryCall; + public get(request: ohlcv_pb.GetRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: ohlcv_pb.GetResponse) => void): grpc.ClientUnaryCall; + public get(request: ohlcv_pb.GetRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: ohlcv_pb.GetResponse) => void): grpc.ClientUnaryCall; +} diff --git a/lib/proto/ohlcv_grpc_pb.js b/lib/proto/ohlcv_grpc_pb.js new file mode 100644 index 0000000..f2c7d8d --- /dev/null +++ b/lib/proto/ohlcv_grpc_pb.js @@ -0,0 +1,46 @@ +// GENERATED CODE -- DO NOT EDIT! + +'use strict'; +var grpc = require('@grpc/grpc-js'); +var ohlcv_pb = require('./ohlcv_pb.js'); +var google_protobuf_timestamp_pb = require('google-protobuf/google/protobuf/timestamp_pb.js'); +var google_protobuf_empty_pb = require('google-protobuf/google/protobuf/empty_pb.js'); + +function serialize_ohlcv_GetRequest(arg) { + if (!(arg instanceof ohlcv_pb.GetRequest)) { + throw new Error('Expected argument of type ohlcv.GetRequest'); + } + return Buffer.from(arg.serializeBinary()); +} + +function deserialize_ohlcv_GetRequest(buffer_arg) { + return ohlcv_pb.GetRequest.deserializeBinary(new Uint8Array(buffer_arg)); +} + +function serialize_ohlcv_GetResponse(arg) { + if (!(arg instanceof ohlcv_pb.GetResponse)) { + throw new Error('Expected argument of type ohlcv.GetResponse'); + } + return Buffer.from(arg.serializeBinary()); +} + +function deserialize_ohlcv_GetResponse(buffer_arg) { + return ohlcv_pb.GetResponse.deserializeBinary(new Uint8Array(buffer_arg)); +} + + +var OhlcvApiService = exports.OhlcvApiService = { + get: { + path: '/ohlcv.OhlcvApi/Get', + requestStream: false, + responseStream: false, + requestType: ohlcv_pb.GetRequest, + responseType: ohlcv_pb.GetResponse, + requestSerialize: serialize_ohlcv_GetRequest, + requestDeserialize: deserialize_ohlcv_GetRequest, + responseSerialize: serialize_ohlcv_GetResponse, + responseDeserialize: deserialize_ohlcv_GetResponse, + }, +}; + +exports.OhlcvApiClient = grpc.makeGenericClientConstructor(OhlcvApiService, 'OhlcvApi'); diff --git a/lib/proto/ohlcv_pb.d.ts b/lib/proto/ohlcv_pb.d.ts new file mode 100644 index 0000000..3608827 --- /dev/null +++ b/lib/proto/ohlcv_pb.d.ts @@ -0,0 +1,157 @@ +// package: ohlcv +// file: ohlcv.proto + +/* tslint:disable */ +/* eslint-disable */ + +import * as jspb from "google-protobuf"; +import * as google_protobuf_timestamp_pb from "google-protobuf/google/protobuf/timestamp_pb"; +import * as google_protobuf_empty_pb from "google-protobuf/google/protobuf/empty_pb"; + +export class GetRequest extends jspb.Message { + getSymId(): string; + setSymId(value: string): GetRequest; + getTimeframe(): string; + setTimeframe(value: string): GetRequest; + + hasLimit(): boolean; + clearLimit(): void; + getLimit(): number | undefined; + setLimit(value: number): GetRequest; + + hasOffset(): boolean; + clearOffset(): void; + getOffset(): number | undefined; + setOffset(value: number): GetRequest; + + hasOrder(): boolean; + clearOrder(): void; + getOrder(): Order | undefined; + setOrder(value: Order): GetRequest; + + hasStartOpenTime(): boolean; + clearStartOpenTime(): void; + getStartOpenTime(): google_protobuf_timestamp_pb.Timestamp | undefined; + setStartOpenTime(value?: google_protobuf_timestamp_pb.Timestamp): GetRequest; + + hasEndOpenTime(): boolean; + clearEndOpenTime(): void; + getEndOpenTime(): google_protobuf_timestamp_pb.Timestamp | undefined; + setEndOpenTime(value?: google_protobuf_timestamp_pb.Timestamp): GetRequest; + + hasStartCloseTime(): boolean; + clearStartCloseTime(): void; + getStartCloseTime(): google_protobuf_timestamp_pb.Timestamp | undefined; + setStartCloseTime(value?: google_protobuf_timestamp_pb.Timestamp): GetRequest; + + hasEndCloseTime(): boolean; + clearEndCloseTime(): void; + getEndCloseTime(): google_protobuf_timestamp_pb.Timestamp | undefined; + setEndCloseTime(value?: google_protobuf_timestamp_pb.Timestamp): GetRequest; + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): GetRequest.AsObject; + static toObject(includeInstance: boolean, msg: GetRequest): GetRequest.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: GetRequest, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): GetRequest; + static deserializeBinaryFromReader(message: GetRequest, reader: jspb.BinaryReader): GetRequest; +} + +export namespace GetRequest { + export type AsObject = { + symId: string, + timeframe: string, + limit?: number, + offset?: number, + order?: Order, + startOpenTime?: google_protobuf_timestamp_pb.Timestamp.AsObject, + endOpenTime?: google_protobuf_timestamp_pb.Timestamp.AsObject, + startCloseTime?: google_protobuf_timestamp_pb.Timestamp.AsObject, + endCloseTime?: google_protobuf_timestamp_pb.Timestamp.AsObject, + } +} + +export class GetResponse extends jspb.Message { + clearBarsList(): void; + getBarsList(): Array; + setBarsList(value: Array): GetResponse; + addBars(value?: OhlcvBar, index?: number): OhlcvBar; + + hasTotal(): boolean; + clearTotal(): void; + getTotal(): number | undefined; + setTotal(value: number): GetResponse; + + hasRemaining(): boolean; + clearRemaining(): void; + getRemaining(): number | undefined; + setRemaining(value: number): GetResponse; + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): GetResponse.AsObject; + static toObject(includeInstance: boolean, msg: GetResponse): GetResponse.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: GetResponse, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): GetResponse; + static deserializeBinaryFromReader(message: GetResponse, reader: jspb.BinaryReader): GetResponse; +} + +export namespace GetResponse { + export type AsObject = { + barsList: Array, + total?: number, + remaining?: number, + } +} + +export class OhlcvBar extends jspb.Message { + + hasOpenTime(): boolean; + clearOpenTime(): void; + getOpenTime(): google_protobuf_timestamp_pb.Timestamp | undefined; + setOpenTime(value?: google_protobuf_timestamp_pb.Timestamp): OhlcvBar; + + hasCloseTime(): boolean; + clearCloseTime(): void; + getCloseTime(): google_protobuf_timestamp_pb.Timestamp | undefined; + setCloseTime(value?: google_protobuf_timestamp_pb.Timestamp): OhlcvBar; + getOpen(): number; + setOpen(value: number): OhlcvBar; + getHigh(): number; + setHigh(value: number): OhlcvBar; + getLow(): number; + setLow(value: number): OhlcvBar; + getClose(): number; + setClose(value: number): OhlcvBar; + getVolume(): number; + setVolume(value: number): OhlcvBar; + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): OhlcvBar.AsObject; + static toObject(includeInstance: boolean, msg: OhlcvBar): OhlcvBar.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: OhlcvBar, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): OhlcvBar; + static deserializeBinaryFromReader(message: OhlcvBar, reader: jspb.BinaryReader): OhlcvBar; +} + +export namespace OhlcvBar { + export type AsObject = { + openTime?: google_protobuf_timestamp_pb.Timestamp.AsObject, + closeTime?: google_protobuf_timestamp_pb.Timestamp.AsObject, + open: number, + high: number, + low: number, + close: number, + volume: number, + } +} + +export enum Order { + ASC = 0, + DESC = 1, +} diff --git a/lib/proto/ohlcv_pb.js b/lib/proto/ohlcv_pb.js new file mode 100644 index 0000000..8027384 --- /dev/null +++ b/lib/proto/ohlcv_pb.js @@ -0,0 +1,1219 @@ +// source: ohlcv.proto +/** + * @fileoverview + * @enhanceable + * @suppress {missingRequire} reports error on implicit type usages. + * @suppress {messageConventions} JS Compiler reports an error if a variable or + * field starts with 'MSG_' and isn't a translatable message. + * @public + */ +// GENERATED CODE -- DO NOT EDIT! +/* eslint-disable */ +// @ts-nocheck + +var jspb = require('google-protobuf'); +var goog = jspb; +var global = (function() { + if (this) { return this; } + if (typeof window !== 'undefined') { return window; } + if (typeof global !== 'undefined') { return global; } + if (typeof self !== 'undefined') { return self; } + return Function('return this')(); +}.call(null)); + +var google_protobuf_timestamp_pb = require('google-protobuf/google/protobuf/timestamp_pb.js'); +goog.object.extend(proto, google_protobuf_timestamp_pb); +var google_protobuf_empty_pb = require('google-protobuf/google/protobuf/empty_pb.js'); +goog.object.extend(proto, google_protobuf_empty_pb); +goog.exportSymbol('proto.ohlcv.GetRequest', null, global); +goog.exportSymbol('proto.ohlcv.GetResponse', null, global); +goog.exportSymbol('proto.ohlcv.OhlcvBar', null, global); +goog.exportSymbol('proto.ohlcv.Order', null, global); +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.ohlcv.GetRequest = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.ohlcv.GetRequest, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.ohlcv.GetRequest.displayName = 'proto.ohlcv.GetRequest'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.ohlcv.GetResponse = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, proto.ohlcv.GetResponse.repeatedFields_, null); +}; +goog.inherits(proto.ohlcv.GetResponse, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.ohlcv.GetResponse.displayName = 'proto.ohlcv.GetResponse'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.ohlcv.OhlcvBar = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.ohlcv.OhlcvBar, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.ohlcv.OhlcvBar.displayName = 'proto.ohlcv.OhlcvBar'; +} + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.ohlcv.GetRequest.prototype.toObject = function(opt_includeInstance) { + return proto.ohlcv.GetRequest.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.ohlcv.GetRequest} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.ohlcv.GetRequest.toObject = function(includeInstance, msg) { + var f, obj = { + symId: jspb.Message.getFieldWithDefault(msg, 1, ""), + timeframe: jspb.Message.getFieldWithDefault(msg, 2, ""), + limit: jspb.Message.getFieldWithDefault(msg, 3, 0), + offset: jspb.Message.getFieldWithDefault(msg, 4, 0), + order: jspb.Message.getFieldWithDefault(msg, 5, 0), + startOpenTime: (f = msg.getStartOpenTime()) && google_protobuf_timestamp_pb.Timestamp.toObject(includeInstance, f), + endOpenTime: (f = msg.getEndOpenTime()) && google_protobuf_timestamp_pb.Timestamp.toObject(includeInstance, f), + startCloseTime: (f = msg.getStartCloseTime()) && google_protobuf_timestamp_pb.Timestamp.toObject(includeInstance, f), + endCloseTime: (f = msg.getEndCloseTime()) && google_protobuf_timestamp_pb.Timestamp.toObject(includeInstance, f) + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.ohlcv.GetRequest} + */ +proto.ohlcv.GetRequest.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.ohlcv.GetRequest; + return proto.ohlcv.GetRequest.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.ohlcv.GetRequest} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.ohlcv.GetRequest} + */ +proto.ohlcv.GetRequest.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {string} */ (reader.readString()); + msg.setSymId(value); + break; + case 2: + var value = /** @type {string} */ (reader.readString()); + msg.setTimeframe(value); + break; + case 3: + var value = /** @type {number} */ (reader.readUint32()); + msg.setLimit(value); + break; + case 4: + var value = /** @type {number} */ (reader.readUint32()); + msg.setOffset(value); + break; + case 5: + var value = /** @type {!proto.ohlcv.Order} */ (reader.readEnum()); + msg.setOrder(value); + break; + case 6: + var value = new google_protobuf_timestamp_pb.Timestamp; + reader.readMessage(value,google_protobuf_timestamp_pb.Timestamp.deserializeBinaryFromReader); + msg.setStartOpenTime(value); + break; + case 7: + var value = new google_protobuf_timestamp_pb.Timestamp; + reader.readMessage(value,google_protobuf_timestamp_pb.Timestamp.deserializeBinaryFromReader); + msg.setEndOpenTime(value); + break; + case 8: + var value = new google_protobuf_timestamp_pb.Timestamp; + reader.readMessage(value,google_protobuf_timestamp_pb.Timestamp.deserializeBinaryFromReader); + msg.setStartCloseTime(value); + break; + case 9: + var value = new google_protobuf_timestamp_pb.Timestamp; + reader.readMessage(value,google_protobuf_timestamp_pb.Timestamp.deserializeBinaryFromReader); + msg.setEndCloseTime(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.ohlcv.GetRequest.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.ohlcv.GetRequest.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.ohlcv.GetRequest} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.ohlcv.GetRequest.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getSymId(); + if (f.length > 0) { + writer.writeString( + 1, + f + ); + } + f = message.getTimeframe(); + if (f.length > 0) { + writer.writeString( + 2, + f + ); + } + f = /** @type {number} */ (jspb.Message.getField(message, 3)); + if (f != null) { + writer.writeUint32( + 3, + f + ); + } + f = /** @type {number} */ (jspb.Message.getField(message, 4)); + if (f != null) { + writer.writeUint32( + 4, + f + ); + } + f = /** @type {!proto.ohlcv.Order} */ (jspb.Message.getField(message, 5)); + if (f != null) { + writer.writeEnum( + 5, + f + ); + } + f = message.getStartOpenTime(); + if (f != null) { + writer.writeMessage( + 6, + f, + google_protobuf_timestamp_pb.Timestamp.serializeBinaryToWriter + ); + } + f = message.getEndOpenTime(); + if (f != null) { + writer.writeMessage( + 7, + f, + google_protobuf_timestamp_pb.Timestamp.serializeBinaryToWriter + ); + } + f = message.getStartCloseTime(); + if (f != null) { + writer.writeMessage( + 8, + f, + google_protobuf_timestamp_pb.Timestamp.serializeBinaryToWriter + ); + } + f = message.getEndCloseTime(); + if (f != null) { + writer.writeMessage( + 9, + f, + google_protobuf_timestamp_pb.Timestamp.serializeBinaryToWriter + ); + } +}; + + +/** + * optional string sym_id = 1; + * @return {string} + */ +proto.ohlcv.GetRequest.prototype.getSymId = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +}; + + +/** + * @param {string} value + * @return {!proto.ohlcv.GetRequest} returns this + */ +proto.ohlcv.GetRequest.prototype.setSymId = function(value) { + return jspb.Message.setProto3StringField(this, 1, value); +}; + + +/** + * optional string timeframe = 2; + * @return {string} + */ +proto.ohlcv.GetRequest.prototype.getTimeframe = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); +}; + + +/** + * @param {string} value + * @return {!proto.ohlcv.GetRequest} returns this + */ +proto.ohlcv.GetRequest.prototype.setTimeframe = function(value) { + return jspb.Message.setProto3StringField(this, 2, value); +}; + + +/** + * optional uint32 limit = 3; + * @return {number} + */ +proto.ohlcv.GetRequest.prototype.getLimit = function() { + return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 3, 0)); +}; + + +/** + * @param {number} value + * @return {!proto.ohlcv.GetRequest} returns this + */ +proto.ohlcv.GetRequest.prototype.setLimit = function(value) { + return jspb.Message.setField(this, 3, value); +}; + + +/** + * Clears the field making it undefined. + * @return {!proto.ohlcv.GetRequest} returns this + */ +proto.ohlcv.GetRequest.prototype.clearLimit = function() { + return jspb.Message.setField(this, 3, undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.ohlcv.GetRequest.prototype.hasLimit = function() { + return jspb.Message.getField(this, 3) != null; +}; + + +/** + * optional uint32 offset = 4; + * @return {number} + */ +proto.ohlcv.GetRequest.prototype.getOffset = function() { + return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 4, 0)); +}; + + +/** + * @param {number} value + * @return {!proto.ohlcv.GetRequest} returns this + */ +proto.ohlcv.GetRequest.prototype.setOffset = function(value) { + return jspb.Message.setField(this, 4, value); +}; + + +/** + * Clears the field making it undefined. + * @return {!proto.ohlcv.GetRequest} returns this + */ +proto.ohlcv.GetRequest.prototype.clearOffset = function() { + return jspb.Message.setField(this, 4, undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.ohlcv.GetRequest.prototype.hasOffset = function() { + return jspb.Message.getField(this, 4) != null; +}; + + +/** + * optional Order order = 5; + * @return {!proto.ohlcv.Order} + */ +proto.ohlcv.GetRequest.prototype.getOrder = function() { + return /** @type {!proto.ohlcv.Order} */ (jspb.Message.getFieldWithDefault(this, 5, 0)); +}; + + +/** + * @param {!proto.ohlcv.Order} value + * @return {!proto.ohlcv.GetRequest} returns this + */ +proto.ohlcv.GetRequest.prototype.setOrder = function(value) { + return jspb.Message.setField(this, 5, value); +}; + + +/** + * Clears the field making it undefined. + * @return {!proto.ohlcv.GetRequest} returns this + */ +proto.ohlcv.GetRequest.prototype.clearOrder = function() { + return jspb.Message.setField(this, 5, undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.ohlcv.GetRequest.prototype.hasOrder = function() { + return jspb.Message.getField(this, 5) != null; +}; + + +/** + * optional google.protobuf.Timestamp start_open_time = 6; + * @return {?proto.google.protobuf.Timestamp} + */ +proto.ohlcv.GetRequest.prototype.getStartOpenTime = function() { + return /** @type{?proto.google.protobuf.Timestamp} */ ( + jspb.Message.getWrapperField(this, google_protobuf_timestamp_pb.Timestamp, 6)); +}; + + +/** + * @param {?proto.google.protobuf.Timestamp|undefined} value + * @return {!proto.ohlcv.GetRequest} returns this +*/ +proto.ohlcv.GetRequest.prototype.setStartOpenTime = function(value) { + return jspb.Message.setWrapperField(this, 6, value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.ohlcv.GetRequest} returns this + */ +proto.ohlcv.GetRequest.prototype.clearStartOpenTime = function() { + return this.setStartOpenTime(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.ohlcv.GetRequest.prototype.hasStartOpenTime = function() { + return jspb.Message.getField(this, 6) != null; +}; + + +/** + * optional google.protobuf.Timestamp end_open_time = 7; + * @return {?proto.google.protobuf.Timestamp} + */ +proto.ohlcv.GetRequest.prototype.getEndOpenTime = function() { + return /** @type{?proto.google.protobuf.Timestamp} */ ( + jspb.Message.getWrapperField(this, google_protobuf_timestamp_pb.Timestamp, 7)); +}; + + +/** + * @param {?proto.google.protobuf.Timestamp|undefined} value + * @return {!proto.ohlcv.GetRequest} returns this +*/ +proto.ohlcv.GetRequest.prototype.setEndOpenTime = function(value) { + return jspb.Message.setWrapperField(this, 7, value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.ohlcv.GetRequest} returns this + */ +proto.ohlcv.GetRequest.prototype.clearEndOpenTime = function() { + return this.setEndOpenTime(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.ohlcv.GetRequest.prototype.hasEndOpenTime = function() { + return jspb.Message.getField(this, 7) != null; +}; + + +/** + * optional google.protobuf.Timestamp start_close_time = 8; + * @return {?proto.google.protobuf.Timestamp} + */ +proto.ohlcv.GetRequest.prototype.getStartCloseTime = function() { + return /** @type{?proto.google.protobuf.Timestamp} */ ( + jspb.Message.getWrapperField(this, google_protobuf_timestamp_pb.Timestamp, 8)); +}; + + +/** + * @param {?proto.google.protobuf.Timestamp|undefined} value + * @return {!proto.ohlcv.GetRequest} returns this +*/ +proto.ohlcv.GetRequest.prototype.setStartCloseTime = function(value) { + return jspb.Message.setWrapperField(this, 8, value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.ohlcv.GetRequest} returns this + */ +proto.ohlcv.GetRequest.prototype.clearStartCloseTime = function() { + return this.setStartCloseTime(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.ohlcv.GetRequest.prototype.hasStartCloseTime = function() { + return jspb.Message.getField(this, 8) != null; +}; + + +/** + * optional google.protobuf.Timestamp end_close_time = 9; + * @return {?proto.google.protobuf.Timestamp} + */ +proto.ohlcv.GetRequest.prototype.getEndCloseTime = function() { + return /** @type{?proto.google.protobuf.Timestamp} */ ( + jspb.Message.getWrapperField(this, google_protobuf_timestamp_pb.Timestamp, 9)); +}; + + +/** + * @param {?proto.google.protobuf.Timestamp|undefined} value + * @return {!proto.ohlcv.GetRequest} returns this +*/ +proto.ohlcv.GetRequest.prototype.setEndCloseTime = function(value) { + return jspb.Message.setWrapperField(this, 9, value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.ohlcv.GetRequest} returns this + */ +proto.ohlcv.GetRequest.prototype.clearEndCloseTime = function() { + return this.setEndCloseTime(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.ohlcv.GetRequest.prototype.hasEndCloseTime = function() { + return jspb.Message.getField(this, 9) != null; +}; + + + +/** + * List of repeated fields within this message type. + * @private {!Array} + * @const + */ +proto.ohlcv.GetResponse.repeatedFields_ = [1]; + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.ohlcv.GetResponse.prototype.toObject = function(opt_includeInstance) { + return proto.ohlcv.GetResponse.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.ohlcv.GetResponse} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.ohlcv.GetResponse.toObject = function(includeInstance, msg) { + var f, obj = { + barsList: jspb.Message.toObjectList(msg.getBarsList(), + proto.ohlcv.OhlcvBar.toObject, includeInstance), + total: jspb.Message.getFieldWithDefault(msg, 2, 0), + remaining: jspb.Message.getFieldWithDefault(msg, 3, 0) + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.ohlcv.GetResponse} + */ +proto.ohlcv.GetResponse.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.ohlcv.GetResponse; + return proto.ohlcv.GetResponse.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.ohlcv.GetResponse} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.ohlcv.GetResponse} + */ +proto.ohlcv.GetResponse.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = new proto.ohlcv.OhlcvBar; + reader.readMessage(value,proto.ohlcv.OhlcvBar.deserializeBinaryFromReader); + msg.addBars(value); + break; + case 2: + var value = /** @type {number} */ (reader.readUint32()); + msg.setTotal(value); + break; + case 3: + var value = /** @type {number} */ (reader.readUint32()); + msg.setRemaining(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.ohlcv.GetResponse.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.ohlcv.GetResponse.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.ohlcv.GetResponse} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.ohlcv.GetResponse.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getBarsList(); + if (f.length > 0) { + writer.writeRepeatedMessage( + 1, + f, + proto.ohlcv.OhlcvBar.serializeBinaryToWriter + ); + } + f = /** @type {number} */ (jspb.Message.getField(message, 2)); + if (f != null) { + writer.writeUint32( + 2, + f + ); + } + f = /** @type {number} */ (jspb.Message.getField(message, 3)); + if (f != null) { + writer.writeUint32( + 3, + f + ); + } +}; + + +/** + * repeated OhlcvBar bars = 1; + * @return {!Array} + */ +proto.ohlcv.GetResponse.prototype.getBarsList = function() { + return /** @type{!Array} */ ( + jspb.Message.getRepeatedWrapperField(this, proto.ohlcv.OhlcvBar, 1)); +}; + + +/** + * @param {!Array} value + * @return {!proto.ohlcv.GetResponse} returns this +*/ +proto.ohlcv.GetResponse.prototype.setBarsList = function(value) { + return jspb.Message.setRepeatedWrapperField(this, 1, value); +}; + + +/** + * @param {!proto.ohlcv.OhlcvBar=} opt_value + * @param {number=} opt_index + * @return {!proto.ohlcv.OhlcvBar} + */ +proto.ohlcv.GetResponse.prototype.addBars = function(opt_value, opt_index) { + return jspb.Message.addToRepeatedWrapperField(this, 1, opt_value, proto.ohlcv.OhlcvBar, opt_index); +}; + + +/** + * Clears the list making it empty but non-null. + * @return {!proto.ohlcv.GetResponse} returns this + */ +proto.ohlcv.GetResponse.prototype.clearBarsList = function() { + return this.setBarsList([]); +}; + + +/** + * optional uint32 total = 2; + * @return {number} + */ +proto.ohlcv.GetResponse.prototype.getTotal = function() { + return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 2, 0)); +}; + + +/** + * @param {number} value + * @return {!proto.ohlcv.GetResponse} returns this + */ +proto.ohlcv.GetResponse.prototype.setTotal = function(value) { + return jspb.Message.setField(this, 2, value); +}; + + +/** + * Clears the field making it undefined. + * @return {!proto.ohlcv.GetResponse} returns this + */ +proto.ohlcv.GetResponse.prototype.clearTotal = function() { + return jspb.Message.setField(this, 2, undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.ohlcv.GetResponse.prototype.hasTotal = function() { + return jspb.Message.getField(this, 2) != null; +}; + + +/** + * optional uint32 remaining = 3; + * @return {number} + */ +proto.ohlcv.GetResponse.prototype.getRemaining = function() { + return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 3, 0)); +}; + + +/** + * @param {number} value + * @return {!proto.ohlcv.GetResponse} returns this + */ +proto.ohlcv.GetResponse.prototype.setRemaining = function(value) { + return jspb.Message.setField(this, 3, value); +}; + + +/** + * Clears the field making it undefined. + * @return {!proto.ohlcv.GetResponse} returns this + */ +proto.ohlcv.GetResponse.prototype.clearRemaining = function() { + return jspb.Message.setField(this, 3, undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.ohlcv.GetResponse.prototype.hasRemaining = function() { + return jspb.Message.getField(this, 3) != null; +}; + + + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.ohlcv.OhlcvBar.prototype.toObject = function(opt_includeInstance) { + return proto.ohlcv.OhlcvBar.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.ohlcv.OhlcvBar} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.ohlcv.OhlcvBar.toObject = function(includeInstance, msg) { + var f, obj = { + openTime: (f = msg.getOpenTime()) && google_protobuf_timestamp_pb.Timestamp.toObject(includeInstance, f), + closeTime: (f = msg.getCloseTime()) && google_protobuf_timestamp_pb.Timestamp.toObject(includeInstance, f), + open: jspb.Message.getFloatingPointFieldWithDefault(msg, 3, 0.0), + high: jspb.Message.getFloatingPointFieldWithDefault(msg, 4, 0.0), + low: jspb.Message.getFloatingPointFieldWithDefault(msg, 5, 0.0), + close: jspb.Message.getFloatingPointFieldWithDefault(msg, 6, 0.0), + volume: jspb.Message.getFloatingPointFieldWithDefault(msg, 7, 0.0) + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.ohlcv.OhlcvBar} + */ +proto.ohlcv.OhlcvBar.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.ohlcv.OhlcvBar; + return proto.ohlcv.OhlcvBar.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.ohlcv.OhlcvBar} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.ohlcv.OhlcvBar} + */ +proto.ohlcv.OhlcvBar.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = new google_protobuf_timestamp_pb.Timestamp; + reader.readMessage(value,google_protobuf_timestamp_pb.Timestamp.deserializeBinaryFromReader); + msg.setOpenTime(value); + break; + case 2: + var value = new google_protobuf_timestamp_pb.Timestamp; + reader.readMessage(value,google_protobuf_timestamp_pb.Timestamp.deserializeBinaryFromReader); + msg.setCloseTime(value); + break; + case 3: + var value = /** @type {number} */ (reader.readDouble()); + msg.setOpen(value); + break; + case 4: + var value = /** @type {number} */ (reader.readDouble()); + msg.setHigh(value); + break; + case 5: + var value = /** @type {number} */ (reader.readDouble()); + msg.setLow(value); + break; + case 6: + var value = /** @type {number} */ (reader.readDouble()); + msg.setClose(value); + break; + case 7: + var value = /** @type {number} */ (reader.readDouble()); + msg.setVolume(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.ohlcv.OhlcvBar.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.ohlcv.OhlcvBar.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.ohlcv.OhlcvBar} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.ohlcv.OhlcvBar.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getOpenTime(); + if (f != null) { + writer.writeMessage( + 1, + f, + google_protobuf_timestamp_pb.Timestamp.serializeBinaryToWriter + ); + } + f = message.getCloseTime(); + if (f != null) { + writer.writeMessage( + 2, + f, + google_protobuf_timestamp_pb.Timestamp.serializeBinaryToWriter + ); + } + f = message.getOpen(); + if (f !== 0.0) { + writer.writeDouble( + 3, + f + ); + } + f = message.getHigh(); + if (f !== 0.0) { + writer.writeDouble( + 4, + f + ); + } + f = message.getLow(); + if (f !== 0.0) { + writer.writeDouble( + 5, + f + ); + } + f = message.getClose(); + if (f !== 0.0) { + writer.writeDouble( + 6, + f + ); + } + f = message.getVolume(); + if (f !== 0.0) { + writer.writeDouble( + 7, + f + ); + } +}; + + +/** + * optional google.protobuf.Timestamp open_time = 1; + * @return {?proto.google.protobuf.Timestamp} + */ +proto.ohlcv.OhlcvBar.prototype.getOpenTime = function() { + return /** @type{?proto.google.protobuf.Timestamp} */ ( + jspb.Message.getWrapperField(this, google_protobuf_timestamp_pb.Timestamp, 1)); +}; + + +/** + * @param {?proto.google.protobuf.Timestamp|undefined} value + * @return {!proto.ohlcv.OhlcvBar} returns this +*/ +proto.ohlcv.OhlcvBar.prototype.setOpenTime = function(value) { + return jspb.Message.setWrapperField(this, 1, value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.ohlcv.OhlcvBar} returns this + */ +proto.ohlcv.OhlcvBar.prototype.clearOpenTime = function() { + return this.setOpenTime(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.ohlcv.OhlcvBar.prototype.hasOpenTime = function() { + return jspb.Message.getField(this, 1) != null; +}; + + +/** + * optional google.protobuf.Timestamp close_time = 2; + * @return {?proto.google.protobuf.Timestamp} + */ +proto.ohlcv.OhlcvBar.prototype.getCloseTime = function() { + return /** @type{?proto.google.protobuf.Timestamp} */ ( + jspb.Message.getWrapperField(this, google_protobuf_timestamp_pb.Timestamp, 2)); +}; + + +/** + * @param {?proto.google.protobuf.Timestamp|undefined} value + * @return {!proto.ohlcv.OhlcvBar} returns this +*/ +proto.ohlcv.OhlcvBar.prototype.setCloseTime = function(value) { + return jspb.Message.setWrapperField(this, 2, value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.ohlcv.OhlcvBar} returns this + */ +proto.ohlcv.OhlcvBar.prototype.clearCloseTime = function() { + return this.setCloseTime(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.ohlcv.OhlcvBar.prototype.hasCloseTime = function() { + return jspb.Message.getField(this, 2) != null; +}; + + +/** + * optional double open = 3; + * @return {number} + */ +proto.ohlcv.OhlcvBar.prototype.getOpen = function() { + return /** @type {number} */ (jspb.Message.getFloatingPointFieldWithDefault(this, 3, 0.0)); +}; + + +/** + * @param {number} value + * @return {!proto.ohlcv.OhlcvBar} returns this + */ +proto.ohlcv.OhlcvBar.prototype.setOpen = function(value) { + return jspb.Message.setProto3FloatField(this, 3, value); +}; + + +/** + * optional double high = 4; + * @return {number} + */ +proto.ohlcv.OhlcvBar.prototype.getHigh = function() { + return /** @type {number} */ (jspb.Message.getFloatingPointFieldWithDefault(this, 4, 0.0)); +}; + + +/** + * @param {number} value + * @return {!proto.ohlcv.OhlcvBar} returns this + */ +proto.ohlcv.OhlcvBar.prototype.setHigh = function(value) { + return jspb.Message.setProto3FloatField(this, 4, value); +}; + + +/** + * optional double low = 5; + * @return {number} + */ +proto.ohlcv.OhlcvBar.prototype.getLow = function() { + return /** @type {number} */ (jspb.Message.getFloatingPointFieldWithDefault(this, 5, 0.0)); +}; + + +/** + * @param {number} value + * @return {!proto.ohlcv.OhlcvBar} returns this + */ +proto.ohlcv.OhlcvBar.prototype.setLow = function(value) { + return jspb.Message.setProto3FloatField(this, 5, value); +}; + + +/** + * optional double close = 6; + * @return {number} + */ +proto.ohlcv.OhlcvBar.prototype.getClose = function() { + return /** @type {number} */ (jspb.Message.getFloatingPointFieldWithDefault(this, 6, 0.0)); +}; + + +/** + * @param {number} value + * @return {!proto.ohlcv.OhlcvBar} returns this + */ +proto.ohlcv.OhlcvBar.prototype.setClose = function(value) { + return jspb.Message.setProto3FloatField(this, 6, value); +}; + + +/** + * optional double volume = 7; + * @return {number} + */ +proto.ohlcv.OhlcvBar.prototype.getVolume = function() { + return /** @type {number} */ (jspb.Message.getFloatingPointFieldWithDefault(this, 7, 0.0)); +}; + + +/** + * @param {number} value + * @return {!proto.ohlcv.OhlcvBar} returns this + */ +proto.ohlcv.OhlcvBar.prototype.setVolume = function(value) { + return jspb.Message.setProto3FloatField(this, 7, value); +}; + + +/** + * @enum {number} + */ +proto.ohlcv.Order = { + ASC: 0, + DESC: 1 +}; + +goog.object.extend(exports, proto.ohlcv); diff --git a/lib/proto/ohlcv_pb2.py b/lib/proto/ohlcv_pb2.py new file mode 100644 index 0000000..d66bec5 --- /dev/null +++ b/lib/proto/ohlcv_pb2.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: ohlcv.proto +# Protobuf Python Version: 6.30.0 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 6, + 30, + 0, + '', + 'ohlcv.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 +from google.protobuf import empty_pb2 as google_dot_protobuf_dot_empty__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0bohlcv.proto\x12\x05ohlcv\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1bgoogle/protobuf/empty.proto\"\xcd\x03\n\nGetRequest\x12\x0e\n\x06sym_id\x18\x01 \x01(\t\x12\x11\n\ttimeframe\x18\x02 \x01(\t\x12\x12\n\x05limit\x18\x03 \x01(\rH\x00\x88\x01\x01\x12\x13\n\x06offset\x18\x04 \x01(\rH\x01\x88\x01\x01\x12 \n\x05order\x18\x05 \x01(\x0e\x32\x0c.ohlcv.OrderH\x02\x88\x01\x01\x12\x38\n\x0fstart_open_time\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.TimestampH\x03\x88\x01\x01\x12\x36\n\rend_open_time\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.TimestampH\x04\x88\x01\x01\x12\x39\n\x10start_close_time\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.TimestampH\x05\x88\x01\x01\x12\x37\n\x0e\x65nd_close_time\x18\t \x01(\x0b\x32\x1a.google.protobuf.TimestampH\x06\x88\x01\x01\x42\x08\n\x06_limitB\t\n\x07_offsetB\x08\n\x06_orderB\x12\n\x10_start_open_timeB\x10\n\x0e_end_open_timeB\x13\n\x11_start_close_timeB\x11\n\x0f_end_close_time\"p\n\x0bGetResponse\x12\x1d\n\x04\x62\x61rs\x18\x01 \x03(\x0b\x32\x0f.ohlcv.OhlcvBar\x12\x12\n\x05total\x18\x02 \x01(\rH\x00\x88\x01\x01\x12\x16\n\tremaining\x18\x03 \x01(\rH\x01\x88\x01\x01\x42\x08\n\x06_totalB\x0c\n\n_remaining\"\xb1\x01\n\x08OhlcvBar\x12-\n\topen_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nclose_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0c\n\x04open\x18\x03 \x01(\x01\x12\x0c\n\x04high\x18\x04 \x01(\x01\x12\x0b\n\x03low\x18\x05 \x01(\x01\x12\r\n\x05\x63lose\x18\x06 \x01(\x01\x12\x0e\n\x06volume\x18\x07 \x01(\x01*\x1a\n\x05Order\x12\x07\n\x03\x41SC\x10\x00\x12\x08\n\x04\x44\x45SC\x10\x01\x32\x38\n\x08OhlcvApi\x12,\n\x03Get\x12\x11.ohlcv.GetRequest\x1a\x12.ohlcv.GetResponseb\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'ohlcv_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + DESCRIPTOR._loaded_options = None + _globals['_ORDER']._serialized_start=842 + _globals['_ORDER']._serialized_end=868 + _globals['_GETREQUEST']._serialized_start=85 + _globals['_GETREQUEST']._serialized_end=546 + _globals['_GETRESPONSE']._serialized_start=548 + _globals['_GETRESPONSE']._serialized_end=660 + _globals['_OHLCVBAR']._serialized_start=663 + _globals['_OHLCVBAR']._serialized_end=840 + _globals['_OHLCVAPI']._serialized_start=870 + _globals['_OHLCVAPI']._serialized_end=926 +# @@protoc_insertion_point(module_scope) diff --git a/lib/proto/ohlcv_pb2.pyi b/lib/proto/ohlcv_pb2.pyi new file mode 100644 index 0000000..fbab0cc --- /dev/null +++ b/lib/proto/ohlcv_pb2.pyi @@ -0,0 +1,67 @@ +from google.protobuf import timestamp_pb2 as _timestamp_pb2 +from google.protobuf import empty_pb2 as _empty_pb2 +from google.protobuf.internal import containers as _containers +from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from collections.abc import Iterable as _Iterable, Mapping as _Mapping +from typing import ClassVar as _ClassVar, Optional as _Optional, Union as _Union + +DESCRIPTOR: _descriptor.FileDescriptor + +class Order(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + ASC: _ClassVar[Order] + DESC: _ClassVar[Order] +ASC: Order +DESC: Order + +class GetRequest(_message.Message): + __slots__ = ("sym_id", "timeframe", "limit", "offset", "order", "start_open_time", "end_open_time", "start_close_time", "end_close_time") + SYM_ID_FIELD_NUMBER: _ClassVar[int] + TIMEFRAME_FIELD_NUMBER: _ClassVar[int] + LIMIT_FIELD_NUMBER: _ClassVar[int] + OFFSET_FIELD_NUMBER: _ClassVar[int] + ORDER_FIELD_NUMBER: _ClassVar[int] + START_OPEN_TIME_FIELD_NUMBER: _ClassVar[int] + END_OPEN_TIME_FIELD_NUMBER: _ClassVar[int] + START_CLOSE_TIME_FIELD_NUMBER: _ClassVar[int] + END_CLOSE_TIME_FIELD_NUMBER: _ClassVar[int] + sym_id: str + timeframe: str + limit: int + offset: int + order: Order + start_open_time: _timestamp_pb2.Timestamp + end_open_time: _timestamp_pb2.Timestamp + start_close_time: _timestamp_pb2.Timestamp + end_close_time: _timestamp_pb2.Timestamp + def __init__(self, sym_id: _Optional[str] = ..., timeframe: _Optional[str] = ..., limit: _Optional[int] = ..., offset: _Optional[int] = ..., order: _Optional[_Union[Order, str]] = ..., start_open_time: _Optional[_Union[_timestamp_pb2.Timestamp, _Mapping]] = ..., end_open_time: _Optional[_Union[_timestamp_pb2.Timestamp, _Mapping]] = ..., start_close_time: _Optional[_Union[_timestamp_pb2.Timestamp, _Mapping]] = ..., end_close_time: _Optional[_Union[_timestamp_pb2.Timestamp, _Mapping]] = ...) -> None: ... + +class GetResponse(_message.Message): + __slots__ = ("bars", "total", "remaining") + BARS_FIELD_NUMBER: _ClassVar[int] + TOTAL_FIELD_NUMBER: _ClassVar[int] + REMAINING_FIELD_NUMBER: _ClassVar[int] + bars: _containers.RepeatedCompositeFieldContainer[OhlcvBar] + total: int + remaining: int + def __init__(self, bars: _Optional[_Iterable[_Union[OhlcvBar, _Mapping]]] = ..., total: _Optional[int] = ..., remaining: _Optional[int] = ...) -> None: ... + +class OhlcvBar(_message.Message): + __slots__ = ("open_time", "close_time", "open", "high", "low", "close", "volume") + OPEN_TIME_FIELD_NUMBER: _ClassVar[int] + CLOSE_TIME_FIELD_NUMBER: _ClassVar[int] + OPEN_FIELD_NUMBER: _ClassVar[int] + HIGH_FIELD_NUMBER: _ClassVar[int] + LOW_FIELD_NUMBER: _ClassVar[int] + CLOSE_FIELD_NUMBER: _ClassVar[int] + VOLUME_FIELD_NUMBER: _ClassVar[int] + open_time: _timestamp_pb2.Timestamp + close_time: _timestamp_pb2.Timestamp + open: float + high: float + low: float + close: float + volume: float + def __init__(self, open_time: _Optional[_Union[_timestamp_pb2.Timestamp, _Mapping]] = ..., close_time: _Optional[_Union[_timestamp_pb2.Timestamp, _Mapping]] = ..., open: _Optional[float] = ..., high: _Optional[float] = ..., low: _Optional[float] = ..., close: _Optional[float] = ..., volume: _Optional[float] = ...) -> None: ... diff --git a/lib/proto/ohlcv_pb2_grpc.py b/lib/proto/ohlcv_pb2_grpc.py new file mode 100644 index 0000000..a9e53dc --- /dev/null +++ b/lib/proto/ohlcv_pb2_grpc.py @@ -0,0 +1,97 @@ +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +"""Client and server classes corresponding to protobuf-defined services.""" +import grpc +import warnings + +from . import ohlcv_pb2 as ohlcv__pb2 + +GRPC_GENERATED_VERSION = '1.72.1' +GRPC_VERSION = grpc.__version__ +_version_not_supported = False + +try: + from grpc._utilities import first_version_is_lower + _version_not_supported = first_version_is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION) +except ImportError: + _version_not_supported = True + +if _version_not_supported: + raise RuntimeError( + f'The grpc package installed is at version {GRPC_VERSION},' + + f' but the generated code in ohlcv_pb2_grpc.py depends on' + + f' grpcio>={GRPC_GENERATED_VERSION}.' + + f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}' + + f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.' + ) + + +class OhlcvApiStub(object): + """Missing associated documentation comment in .proto file.""" + + def __init__(self, channel): + """Constructor. + + Args: + channel: A grpc.Channel. + """ + self.Get = channel.unary_unary( + '/ohlcv.OhlcvApi/Get', + request_serializer=ohlcv__pb2.GetRequest.SerializeToString, + response_deserializer=ohlcv__pb2.GetResponse.FromString, + _registered_method=True) + + +class OhlcvApiServicer(object): + """Missing associated documentation comment in .proto file.""" + + def Get(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + +def add_OhlcvApiServicer_to_server(servicer, server): + rpc_method_handlers = { + 'Get': grpc.unary_unary_rpc_method_handler( + servicer.Get, + request_deserializer=ohlcv__pb2.GetRequest.FromString, + response_serializer=ohlcv__pb2.GetResponse.SerializeToString, + ), + } + generic_handler = grpc.method_handlers_generic_handler( + 'ohlcv.OhlcvApi', rpc_method_handlers) + server.add_generic_rpc_handlers((generic_handler,)) + server.add_registered_method_handlers('ohlcv.OhlcvApi', rpc_method_handlers) + + + # This class is part of an EXPERIMENTAL API. +class OhlcvApi(object): + """Missing associated documentation comment in .proto file.""" + + @staticmethod + def Get(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/ohlcv.OhlcvApi/Get', + ohlcv__pb2.GetRequest.SerializeToString, + ohlcv__pb2.GetResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) From cf1aa5df57955b343df74f30f103b7e9bc3433e7 Mon Sep 17 00:00:00 2001 From: xnerhu Date: Mon, 4 Aug 2025 12:10:02 +0200 Subject: [PATCH 2/5] 0.2.7 --- Cargo.lock | 54 ++++++++++++++++++++++++++++++++--- cli/profile.ts | 2 +- cli/user.ts | 2 +- core/Cargo.toml | 2 +- core/backtest.rs | 59 +++++++++++++++++++++++++++++++-------- core/backtest_node.rs | 18 +++++++++--- core/backtest_py.rs | 20 +++++++++---- core/backtest_wasm.rs | 18 +++++++++--- core/lib.rs | 1 + core/metrics.rs | 15 +++++++++- core/metrics_node.rs | 22 +++++++++++---- core/metrics_py.rs | 23 +++++++++++---- core/metrics_wasm.rs | 22 +++++++++++---- core/ohlcv.rs | 19 +++++++++++++ core/stats.rs | 4 +++ core/stats_node.rs | 5 +++- core/stats_py.rs | 2 ++ core/stats_wasm.rs | 5 +++- core/sym.rs | 9 ++++++ core/sym_node.rs | 6 ++++ core/sym_py.rs | 6 ++++ core/sym_wasm.rs | 6 ++++ lib/node/client.ts | 65 +++++++++++++++++++++++++++++++++++++------ package.json | 2 +- 24 files changed, 325 insertions(+), 62 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6ce5c86..ba6bd27 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1728,6 +1728,26 @@ dependencies = [ "syn 2.0.98", ] +[[package]] +name = "pyo3-stub-gen" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e2906d67f2fa9b6079665a1d097c25530f54a8a6a40da5544370786f0adb523" +dependencies = [ + "anyhow", + "chrono", + "inventory", + "itertools 0.13.0", + "log", + "maplit", + "num-complex", + "numpy", + "pyo3", + "pyo3-stub-gen-derive 0.6.2", + "serde", + "toml", +] + [[package]] name = "pyo3-stub-gen" version = "0.7.0" @@ -1743,11 +1763,22 @@ dependencies = [ "num-complex", "numpy", "pyo3", - "pyo3-stub-gen-derive", + "pyo3-stub-gen-derive 0.7.0", "serde", "toml", ] +[[package]] +name = "pyo3-stub-gen-derive" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea3f50b3dca9a392772e45ed6db1066773c74d2be00399f46ab53cbab67a36f9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.98", +] + [[package]] name = "pyo3-stub-gen-derive" version = "0.7.0" @@ -1768,9 +1799,13 @@ dependencies = [ "cc", ] +[[package]] +name = "qpace" +version = "0.0.1-dev.1" + [[package]] name = "qpace_core" -version = "0.2.6" +version = "0.2.7" dependencies = [ "cfg-if", "chrono", @@ -1790,8 +1825,8 @@ dependencies = [ "pyo3", "pyo3-build-config", "pyo3-ffi", - "pyo3-stub-gen", - "pyo3-stub-gen-derive", + "pyo3-stub-gen 0.7.0", + "pyo3-stub-gen-derive 0.7.0", "serde", "serde_json", "textplots", @@ -1799,6 +1834,17 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "qpace_playground_lib" +version = "0.0.1" +dependencies = [ + "pyo3", + "pyo3-ffi", + "pyo3-stub-gen 0.6.2", + "pyo3-stub-gen-derive 0.6.2", + "qpace_core", +] + [[package]] name = "quote" version = "1.0.38" diff --git a/cli/profile.ts b/cli/profile.ts index c497acf..cd09035 100644 --- a/cli/profile.ts +++ b/cli/profile.ts @@ -84,7 +84,7 @@ export class Profile { public async ping(): Promise { const client = await this.getClient(); try { - await client.me(); + await client.user.me(); } catch (e) { if (axios.isAxiosError(e) && e.response?.status == 403) { throw new CliError( diff --git a/cli/user.ts b/cli/user.ts index fc18c5a..81cb63d 100644 --- a/cli/user.ts +++ b/cli/user.ts @@ -20,7 +20,7 @@ export const getCommands = (): Command[] => { profile.data.apiKey = apiKey; const client = await profile.getClient(false); try { - const user = await client.me(); + const user = await client.user.me(); verbose && console.log( `${QPACE_BG_PREFIX}Logged in as ${chalk.yellowBright( diff --git a/core/Cargo.toml b/core/Cargo.toml index 712c871..37dfa3b 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "qpace_core" -version = "0.2.6" +version = "0.2.7" edition = "2021" [lib] diff --git a/core/backtest.rs b/core/backtest.rs index 98107da..6cfdd33 100644 --- a/core/backtest.rs +++ b/core/backtest.rs @@ -1,10 +1,12 @@ +use chrono::{DateTime, Utc}; + use crate::{ ctx::{Ctx, CtxSkip}, legacy::Float64Utils, metrics::{ - avg_losing_trade, avg_trade, avg_win_loss_ratio, avg_winning_trade, gross_loss_pct, - gross_profit_pct, net_profit_pct, profit_factor, sharpe_ratio_from_returns, - sortino_ratio_from_returns, win_rate, + annualization_factor, avg_losing_trade, avg_trade, avg_win_loss_ratio, avg_winning_trade, + expectancy, gross_loss_pct, gross_profit_pct, net_profit_pct, profit_factor, + sharpe_ratio_from_returns, sortino_ratio_from_returns, win_rate, }, orderbook::{ order_size_for_equity_pct, round_contracts, round_to_min_tick, validate_contracts, @@ -13,6 +15,7 @@ use crate::{ signal::{Signal, SignalKind}, stats::returns, sym::Sym, + timeframe::Timeframe, trade::{Trade, TradeError, TradeEvent}, utils::with_suffix, }; @@ -37,6 +40,8 @@ pub struct BacktestConfig { initial_capital: f64, process_orders_on_close: bool, debug: bool, + risk_free_rate: f64, + annualization_factor: f64, } impl Default for BacktestConfig { @@ -45,6 +50,8 @@ impl Default for BacktestConfig { initial_capital: 1000.0, process_orders_on_close: false, debug: false, + risk_free_rate: f64::NAN, + annualization_factor: f64::NAN, } } } @@ -55,6 +62,8 @@ impl BacktestConfig { initial_capital, process_orders_on_close, debug: false, + risk_free_rate: f64::NAN, + annualization_factor: f64::NAN, }; } @@ -87,6 +96,16 @@ impl BacktestConfig { pub fn set_debug(&mut self, debug: bool) { self.debug = debug; } + + #[inline] + pub fn set_risk_free_rate(&mut self, risk_free_rate: f64) { + self.risk_free_rate = risk_free_rate; + } + + #[inline] + pub fn set_annualization_factor(&mut self, annualization_factor: f64) { + self.annualization_factor = annualization_factor; + } } pub struct Backtest { @@ -117,12 +136,19 @@ pub struct Backtest { impl Backtest { #[inline] - pub fn new(ctx: Rc>, config: BacktestConfig) -> Self { + pub fn new(ctx: Rc>, mut config: BacktestConfig) -> Self { let sym = ctx.borrow().sym().clone(); assert!( !f64::is_nan(sym.min_qty()) && !f64::is_nan(sym.min_tick()), "Ctx Symbol is not suitable for backtesting, min_qty is NaN or min_tick is NaN" ); + if config.risk_free_rate.is_nan() { + config.risk_free_rate = 0.0; + } + if config.annualization_factor.is_nan() { + config.annualization_factor = + annualization_factor(ctx.borrow().ohlcv().timeframe(), sym.kind().trading_days()); + } let initial_capital = config.initial_capital; Self { ctx, @@ -273,13 +299,20 @@ impl Backtest { } #[inline] - pub fn sharpe_ratio(&self, rfr: f64) -> f64 { - sharpe_ratio_from_returns(&self.returns_list(), rfr) + pub fn sharpe_ratio(&self) -> f64 { + sharpe_ratio_from_returns(&self.returns_list(), self.config.risk_free_rate) + * self.config.annualization_factor + } + + #[inline] + pub fn sortino_ratio(&self) -> f64 { + sortino_ratio_from_returns(&self.returns_list(), self.config.risk_free_rate) + * self.config.annualization_factor } #[inline] - pub fn sortino_ratio(&self, rfr: f64) -> f64 { - sortino_ratio_from_returns(&self.returns_list(), rfr) + pub fn expectancy(&self) -> f64 { + expectancy(&self.pnl_list()) } #[inline] @@ -817,7 +850,6 @@ for i = 0 to array.size(trades) - 1 #[cfg(feature = "pretty_table")] pub fn print_table(&self) { - let rfr = 0.0; let sym = self.ctx.borrow().sym().clone(); let f_price = with_suffix(&format!(" {}", sym._currency())); let f_percent = with_suffix("%"); @@ -846,12 +878,12 @@ for i = 0 to array.size(trades) - 1 table.add_row(Row::from(vec![ Cell::new("Sharpe Ratio"), - Cell::new(format!("{:0.3}", self.sharpe_ratio(rfr))), + Cell::new(format!("{:0.3}", self.sharpe_ratio())), ])); table.add_row(Row::from(vec![ Cell::new("Sortino Ratio"), - Cell::new(format!("{:0.3}", self.sortino_ratio(rfr))), + Cell::new(format!("{:0.3}", self.sortino_ratio())), ])); table.add_row(Row::from(vec![ @@ -904,6 +936,11 @@ for i = 0 to array.size(trades) - 1 Cell::new(f_raw(self.avg_win_loss_ratio())), ])); + table.add_row(Row::from(vec![ + Cell::new("Expectancy"), + Cell::new(f_raw(self.expectancy())), + ])); + // Print the table println!("{}", table); } diff --git a/core/backtest_node.rs b/core/backtest_node.rs index 31ee679..a3ee28d 100644 --- a/core/backtest_node.rs +++ b/core/backtest_node.rs @@ -31,12 +31,16 @@ impl NodeBacktest { ctx: &NodeCtx, initial_capital: Option, process_orders_on_close: Option, + risk_free_rate: Option, + annualization_factor: Option, ) -> Self { let initial_capital = initial_capital.unwrap_or(1000.0); let process_orders_on_close = process_orders_on_close.unwrap_or(false); let mut config = BacktestConfig::default(); config.set_initial_capital(initial_capital); config.set_process_orders_on_close(process_orders_on_close); + config.set_risk_free_rate(risk_free_rate.unwrap_or(f64::NAN)); + config.set_annualization_factor(annualization_factor.unwrap_or(f64::NAN)); Self { inner: Rc::new(RefCell::new(Backtest::new(ctx.inner().clone(), config))), ctx: ctx.clone(), @@ -177,14 +181,20 @@ impl NodeBacktest { #[napi(js_name = "sharpeRatio")] #[inline] - pub fn node_sharpe_ratio(&self, rfr: f64) -> f64 { - self.inner.borrow().sharpe_ratio(rfr) + pub fn node_sharpe_ratio(&self) -> f64 { + self.inner.borrow().sharpe_ratio() } #[napi(js_name = "sortinoRatio")] #[inline] - pub fn node_sortino_ratio(&self, rfr: f64) -> f64 { - self.inner.borrow().sortino_ratio(rfr) + pub fn node_sortino_ratio(&self) -> f64 { + self.inner.borrow().sortino_ratio() + } + + #[napi(js_name = "expectancy")] + #[inline] + pub fn node_expectancy(&self) -> f64 { + self.inner.borrow().expectancy() } #[napi(js_name = winningTradesCount)] diff --git a/core/backtest_py.rs b/core/backtest_py.rs index 4722228..457d060 100644 --- a/core/backtest_py.rs +++ b/core/backtest_py.rs @@ -29,7 +29,7 @@ impl PyBacktest { #[gen_stub_pymethods] #[pymethods] impl PyBacktest { - #[pyo3(signature = (ctx, initial_capital=1000.0, process_orders_on_close=false, debug=false))] + #[pyo3(signature = (ctx, initial_capital=1000.0, process_orders_on_close=false, debug=false, risk_free_rate=None, annualization_factor=None))] #[new] #[inline] pub fn py_new( @@ -37,11 +37,15 @@ impl PyBacktest { initial_capital: f64, process_orders_on_close: bool, debug: bool, + risk_free_rate: Option, + annualization_factor: Option, ) -> Self { let mut config = BacktestConfig::default(); config.set_initial_capital(initial_capital); config.set_process_orders_on_close(process_orders_on_close); config.set_debug(debug); + config.set_risk_free_rate(risk_free_rate.unwrap_or(f64::NAN)); + config.set_annualization_factor(annualization_factor.unwrap_or(f64::NAN)); Self { inner: Rc::new(RefCell::new(Backtest::new(ctx.inner().clone(), config))), ctx, @@ -183,14 +187,20 @@ impl PyBacktest { #[pyo3(name = "sharpe_ratio")] #[inline] - pub fn py_sharpe_ratio(&self, rfr: f64) -> f64 { - self.inner.borrow().sharpe_ratio(rfr) + pub fn py_sharpe_ratio(&self) -> f64 { + self.inner.borrow().sharpe_ratio() } #[pyo3(name = "sortino_ratio")] #[inline] - pub fn py_sortino_ratio(&self, rfr: f64) -> f64 { - self.inner.borrow().sortino_ratio(rfr) + pub fn py_sortino_ratio(&self) -> f64 { + self.inner.borrow().sortino_ratio() + } + + #[pyo3(name = "expectancy")] + #[inline] + pub fn py_expectancy(&self) -> f64 { + self.inner.borrow().expectancy() } #[getter(position_size)] diff --git a/core/backtest_wasm.rs b/core/backtest_wasm.rs index 60da7a5..85ea247 100644 --- a/core/backtest_wasm.rs +++ b/core/backtest_wasm.rs @@ -42,12 +42,16 @@ impl WasmBacktest { ctx: WasmCtx, initial_capital: Option, process_orders_on_close: Option, + risk_free_rate: Option, + annualization_factor: Option, ) -> Self { let initial_capital = initial_capital.unwrap_or(1000.0); let process_orders_on_close = process_orders_on_close.unwrap_or(false); let mut config = BacktestConfig::default(); config.set_initial_capital(initial_capital); config.set_process_orders_on_close(process_orders_on_close); + config.set_risk_free_rate(risk_free_rate.unwrap_or(f64::NAN)); + config.set_annualization_factor(annualization_factor.unwrap_or(f64::NAN)); Self { inner: Rc::new(RefCell::new(Backtest::new(ctx.inner().clone(), config))), ctx, @@ -188,14 +192,20 @@ impl WasmBacktest { #[wasm_bindgen(js_name = "sharpeRatio")] #[inline] - pub fn wasm_sharpe_ratio(&self, rfr: f64) -> f64 { - self.inner.borrow().sharpe_ratio(rfr) + pub fn wasm_sharpe_ratio(&self) -> f64 { + self.inner.borrow().sharpe_ratio() } #[wasm_bindgen(js_name = "sortinoRatio")] #[inline] - pub fn wasm_sortino_ratio(&self, rfr: f64) -> f64 { - self.inner.borrow().sortino_ratio(rfr) + pub fn wasm_sortino_ratio(&self) -> f64 { + self.inner.borrow().sortino_ratio() + } + + #[wasm_bindgen(js_name = "expectancy")] + #[inline] + pub fn wasm_expectancy(&self) -> f64 { + self.inner.borrow().expectancy() } #[wasm_bindgen(getter = winningTradesCount)] diff --git a/core/lib.rs b/core/lib.rs index dac0538..af6cb84 100644 --- a/core/lib.rs +++ b/core/lib.rs @@ -146,6 +146,7 @@ fn py_lib_mod(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_function(wrap_pyfunction!(metrics_py::py_precision, m)?)?; m.add_function(wrap_pyfunction!(metrics_py::py_recall, m)?)?; m.add_function(wrap_pyfunction!(metrics_py::py_f1, m)?)?; + m.add_function(wrap_pyfunction!(metrics_py::py_annualization_factor, m)?)?; Ok(()) } define_stub_info_gatherer!(stub_info); diff --git a/core/metrics.rs b/core/metrics.rs index 099dfc2..a746263 100644 --- a/core/metrics.rs +++ b/core/metrics.rs @@ -1,4 +1,9 @@ -use crate::stats::{mean, stdev, sum}; +use chrono::Duration; + +use crate::{ + stats::{mean, stdev, sum}, + timeframe::Timeframe, +}; #[inline] pub fn expectancy(pnl: &[f64]) -> f64 { @@ -237,3 +242,11 @@ pub fn f1(precision: f64, recall: f64) -> f64 { // pub fn max_run_up_pct(max_run_up: f64, bar_equity_max: f64) -> f64 { // return max_run_up / bar_equity_max; // } + +#[inline] +pub fn annualization_factor(timeframe: Timeframe, trading_days: f64) -> f64 { + let timeframe_duration: Duration = timeframe.try_into().unwrap(); + let seconds_per_year = trading_days * 24.0 * 60.0 * 60.0; + let seconds_per_timeframe = timeframe_duration.num_seconds() as f64; + return seconds_per_year / seconds_per_timeframe * trading_days as f64; +} diff --git a/core/metrics_node.rs b/core/metrics_node.rs index 0257962..154b042 100644 --- a/core/metrics_node.rs +++ b/core/metrics_node.rs @@ -1,9 +1,13 @@ -use crate::metrics::{ - accuracy, avg_losing_trade, avg_trade, avg_win_loss_ratio, avg_winning_trade, expectancy, - expectancy_score, f1, gross_loss_pct, gross_profit_pct, long_net_profit_pct, - long_net_profit_ratio, net_profit_pct, omega_ratio, omega_ratio_from_returns, pnl, precision, - profit_factor, recall, sharpe_ratio, sharpe_ratio_from_returns, short_net_profit_pct, - sortino_ratio, sortino_ratio_from_returns, win_rate, +use crate::{ + metrics::{ + accuracy, annualization_factor, avg_losing_trade, avg_trade, avg_win_loss_ratio, + avg_winning_trade, expectancy, expectancy_score, f1, gross_loss_pct, gross_profit_pct, + long_net_profit_pct, long_net_profit_ratio, net_profit_pct, omega_ratio, + omega_ratio_from_returns, pnl, precision, profit_factor, recall, sharpe_ratio, + sharpe_ratio_from_returns, short_net_profit_pct, sortino_ratio, sortino_ratio_from_returns, + win_rate, + }, + timeframe_node::NodeTimeframe, }; use napi_derive::napi; @@ -164,3 +168,9 @@ pub fn node_recall(tp_count: f64, fn_count: f64) -> f64 { pub fn node_f1(precision: f64, recall: f64) -> f64 { f1(precision, recall) } + +#[napi(js_name = "annualization_factor")] +#[inline] +pub fn node_annualization_factor(timeframe: &NodeTimeframe, trading_days: f64) -> f64 { + return annualization_factor(timeframe.into(), trading_days); +} diff --git a/core/metrics_py.rs b/core/metrics_py.rs index 62f7ab1..497cbd7 100644 --- a/core/metrics_py.rs +++ b/core/metrics_py.rs @@ -1,9 +1,13 @@ -use crate::metrics::{ - accuracy, avg_losing_trade, avg_trade, avg_win_loss_ratio, avg_winning_trade, expectancy, - expectancy_score, f1, gross_loss_pct, gross_profit_pct, long_net_profit_pct, - long_net_profit_ratio, net_profit_pct, omega_ratio, omega_ratio_from_returns, pnl, precision, - profit_factor, recall, sharpe_ratio, sharpe_ratio_from_returns, short_net_profit_pct, - sortino_ratio, sortino_ratio_from_returns, win_rate, +use crate::{ + metrics::{ + accuracy, annualization_factor, avg_losing_trade, avg_trade, avg_win_loss_ratio, + avg_winning_trade, expectancy, expectancy_score, f1, gross_loss_pct, gross_profit_pct, + long_net_profit_pct, long_net_profit_ratio, net_profit_pct, omega_ratio, + omega_ratio_from_returns, pnl, precision, profit_factor, recall, sharpe_ratio, + sharpe_ratio_from_returns, short_net_profit_pct, sortino_ratio, sortino_ratio_from_returns, + win_rate, + }, + timeframe_py::PyTimeframe, }; use pyo3::prelude::*; use pyo3_stub_gen::derive::gen_stub_pyfunction; @@ -190,3 +194,10 @@ pub fn py_recall(tp_count: f64, fn_count: f64) -> f64 { pub fn py_f1(precision: f64, recall: f64) -> f64 { return f1(precision, recall); } + +#[gen_stub_pyfunction] +#[pyfunction(name = "annualization_factor")] +#[inline] +pub fn py_annualization_factor(timeframe: PyTimeframe, trading_days: f64) -> f64 { + return annualization_factor(timeframe.into(), trading_days); +} diff --git a/core/metrics_wasm.rs b/core/metrics_wasm.rs index 944a9e4..99b5837 100644 --- a/core/metrics_wasm.rs +++ b/core/metrics_wasm.rs @@ -1,9 +1,13 @@ -use crate::metrics::{ - accuracy, avg_losing_trade, avg_trade, avg_win_loss_ratio, avg_winning_trade, expectancy, - expectancy_score, f1, gross_loss_pct, gross_profit_pct, long_net_profit_pct, - long_net_profit_ratio, net_profit_pct, omega_ratio, omega_ratio_from_returns, pnl, precision, - profit_factor, recall, sharpe_ratio, sharpe_ratio_from_returns, short_net_profit_pct, - sortino_ratio, sortino_ratio_from_returns, win_rate, +use crate::{ + metrics::{ + accuracy, annualization_factor, avg_losing_trade, avg_trade, avg_win_loss_ratio, + avg_winning_trade, expectancy, expectancy_score, f1, gross_loss_pct, gross_profit_pct, + long_net_profit_pct, long_net_profit_ratio, net_profit_pct, omega_ratio, + omega_ratio_from_returns, pnl, precision, profit_factor, recall, sharpe_ratio, + sharpe_ratio_from_returns, short_net_profit_pct, sortino_ratio, sortino_ratio_from_returns, + win_rate, + }, + timeframe_wasm::WasmTimeframe, }; use wasm_bindgen::prelude::*; @@ -164,3 +168,9 @@ pub fn wasm_recall(tp_count: f64, fn_count: f64) -> f64 { pub fn wasm_f1(precision: f64, recall: f64) -> f64 { f1(precision, recall) } + +#[wasm_bindgen(js_name = "annualization_factor")] +#[inline] +pub fn wasm_annualization_factor(timeframe: WasmTimeframe, trading_days: f64) -> f64 { + return annualization_factor(timeframe.into(), trading_days); +} diff --git a/core/ohlcv.rs b/core/ohlcv.rs index dcc551d..4910af5 100644 --- a/core/ohlcv.rs +++ b/core/ohlcv.rs @@ -283,6 +283,10 @@ pub trait OhlcvReader: fmt::Debug { self.get(idx) } + fn timeframe(&self) -> Timeframe { + Timeframe::Unknown() + } + fn slice(&self, range: Range) -> Vec; fn bars(&self) -> Vec { return self.slice(0..self.len()); @@ -625,6 +629,11 @@ impl OhlcvReader for Ohlcv { fn as_any(&self) -> &dyn Any { self } + + #[inline] + fn timeframe(&self) -> Timeframe { + self.timeframe + } } impl OhlcvWriter for Ohlcv { @@ -799,6 +808,11 @@ impl OhlcvReader for RcOhlcv { fn as_any(&self) -> &dyn Any { self } + + #[inline] + fn timeframe(&self) -> Timeframe { + self.inner.borrow().timeframe() + } } impl OhlcvWriter for RcOhlcv { @@ -953,6 +967,11 @@ impl OhlcvReader for ArcOhlcv { fn as_any(&self) -> &dyn Any { self } + + #[inline] + fn timeframe(&self) -> Timeframe { + self.inner.read().unwrap().timeframe() + } } impl OhlcvWriter for ArcOhlcv { diff --git a/core/stats.rs b/core/stats.rs index 00fd26b..b4291e2 100644 --- a/core/stats.rs +++ b/core/stats.rs @@ -1,3 +1,7 @@ +use chrono::Duration; + +use crate::timeframe::Timeframe; + #[inline] pub fn sum(values: &[f64]) -> f64 { return values.iter().sum(); diff --git a/core/stats_node.rs b/core/stats_node.rs index 0b53678..83dfaf2 100644 --- a/core/stats_node.rs +++ b/core/stats_node.rs @@ -1,4 +1,7 @@ -use crate::stats::{mean, returns, stdev, sum, var}; +use crate::{ + stats::{mean, returns, stdev, sum, var}, + timeframe_node::NodeTimeframe, +}; use napi_derive::napi; #[napi(js_name = "sum")] diff --git a/core/stats_py.rs b/core/stats_py.rs index e69de29..69cc6a9 100644 --- a/core/stats_py.rs +++ b/core/stats_py.rs @@ -0,0 +1,2 @@ +use pyo3::prelude::*; +use pyo3_stub_gen::derive::{gen_stub_pyclass, gen_stub_pymethods}; diff --git a/core/stats_wasm.rs b/core/stats_wasm.rs index c12be0d..3e2b7ac 100644 --- a/core/stats_wasm.rs +++ b/core/stats_wasm.rs @@ -1,4 +1,7 @@ -use crate::stats::{mean, returns, stdev, sum, var}; +use crate::{ + stats::{mean, returns, stdev, sum, var}, + timeframe_wasm::WasmTimeframe, +}; use wasm_bindgen::prelude::*; #[wasm_bindgen(js_name = "sum")] diff --git a/core/sym.rs b/core/sym.rs index 26f8344..b37b71d 100644 --- a/core/sym.rs +++ b/core/sym.rs @@ -11,6 +11,15 @@ pub enum SymKind { Other(String), } +impl SymKind { + pub fn trading_days(&self) -> f64 { + match self { + SymKind::Crypto => 365.0, + _ => 252.0, + } + } +} + impl Default for SymKind { #[inline] fn default() -> Self { diff --git a/core/sym_node.rs b/core/sym_node.rs index 2e0a785..8e37485 100644 --- a/core/sym_node.rs +++ b/core/sym_node.rs @@ -72,6 +72,12 @@ impl NodeSymKind { pub fn node_eq(&self, other: &NodeSymKind) -> bool { self.inner == other.inner } + + #[napi(getter = tradingDays)] + #[inline] + pub fn node_trading_days(&self) -> f64 { + self.inner.trading_days() + } } #[napi] diff --git a/core/sym_py.rs b/core/sym_py.rs index 98b594b..161e2ec 100644 --- a/core/sym_py.rs +++ b/core/sym_py.rs @@ -101,6 +101,12 @@ impl PySymKind { pub fn py_other(kind: String) -> Self { SymKind::Other(kind).into() } + + #[getter(trading_days)] + #[inline] + pub fn py_trading_days(&self) -> f64 { + self.inner.trading_days() + } } #[gen_stub_pyclass] diff --git a/core/sym_wasm.rs b/core/sym_wasm.rs index f5a9cf0..c37de3e 100644 --- a/core/sym_wasm.rs +++ b/core/sym_wasm.rs @@ -90,6 +90,12 @@ impl WasmSymKind { pub fn wasm_eq(&self, other: WasmSymKind) -> bool { self.inner == other.inner } + + #[wasm_bindgen(getter = tradingDays)] + #[inline] + pub fn wasm_trading_days(&self) -> f64 { + self.inner.trading_days() + } } #[wasm_bindgen(js_name = "Sym")] diff --git a/lib/node/client.ts b/lib/node/client.ts index d197927..c3ce512 100644 --- a/lib/node/client.ts +++ b/lib/node/client.ts @@ -4,6 +4,7 @@ import { version as VERSION, coreVersion as CORE_VERSION, } from "../../package.json"; +import { Timeframe, Sym } from "./index"; // export const DEFAULT_REST_ENDPOINT = `http://0.0.0.0:3000/v1`; // export const DEFAULT_GRPC_ENDPOINT = `0.0.0.0:3001`; @@ -19,11 +20,62 @@ export interface ClientConfig { grpcCredentials?: grpc.ChannelCredentials; } +class UserClient { + constructor(private readonly client: Client) {} + + public async me(): Promise<{ id: string; firstName?: string }> { + const { + data: { user }, + } = await this.client.http.get(`/api-keys/${this.client.config.apiKey}`); + return user; + } +} + +type SymFilter = { + id?: string; + tickerId?: string; + timeframe?: Timeframe | string; + limit?: number; + offset?: number; +}; + +class SymClient { + constructor(private readonly client: Client) {} + + public async get(query: SymFilter | string): Promise { + const _query: SymFilter = { + ...(typeof query === "string" ? { id: query, tickerId: query } : query), + limit: 1, + }; + const syms = await this.syms(_query); + if (syms.length === 0) { + throw new Error("Symbol not found"); + } + return syms[0]; + } + + public async syms(query: SymFilter = {}): Promise { + const timeframe = query?.timeframe?.toString(); + const { data } = await this.client.http.get(`/symbols`, { + params: { + id_pat: query.id, + ticker_id_pat: query.tickerId, + limit: query?.limit, + offset: query?.offset, + timeframe, + }, + }); + return data["symbols"].map((r: any) => Sym.fromJSON(r)); + } +} + export class Client { private _clientInfo: Record = {}; private _http!: AxiosInstance; private _grpcMetadata: grpc.Metadata | undefined; private _grpcOptions: grpc.ClientOptions; + public readonly user: UserClient; + public readonly sym: SymClient; constructor(public readonly config: ClientConfig) { this.config.apiBase ??= DEFAULT_REST_ENDPOINT; @@ -42,9 +94,11 @@ export class Client { "grpc.max_receive_message_length": -1, "grpc.max_send_message_length": -1, }; + this.user = new UserClient(this); + this.sym = new SymClient(this); } - private get http(): AxiosInstance { + public get http(): AxiosInstance { if (this._http == null) { this._http = axios.create({ baseURL: this.config.apiBase, @@ -59,7 +113,7 @@ export class Client { return this._http; } - private get grpcMetadata(): grpc.Metadata { + public get grpcMetadata(): grpc.Metadata { if (this._grpcMetadata == null) { const metadata = new grpc.Metadata(); metadata.set("x-api-key", `${this.config.apiKey}`); @@ -70,11 +124,4 @@ export class Client { } return this._grpcMetadata.clone(); } - - public async me(): Promise<{ id: string; firstName?: string }> { - const { - data: { user }, - } = await this.http.get(`/api-keys/${this.config.apiKey}`); - return user; - } } diff --git a/package.json b/package.json index 74b4aa2..e902ad3 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "qpace", "version": "0.2.6", - "coreVersion": "0.2.6", + "coreVersion": "0.2.7", "description": "📊 The Quant SDK for Python and Javascript. Written in Rust.", "keywords": [ "quant", From 200dfc7ee25022ebed396ae0be244803d0c49f63 Mon Sep 17 00:00:00 2001 From: xnerhu Date: Mon, 4 Aug 2025 12:44:07 +0200 Subject: [PATCH 3/5] update readme --- README.md | 2 ++ lib/node/client.ts | 2 +- static/indicator_banner.png | Bin 0 -> 153994 bytes 3 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 static/indicator_banner.png diff --git a/README.md b/README.md index cb87a59..ddb74c5 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,8 @@ - CLI + upcoming UI +[![indicator plot](/static/indicator_banner.png)](/examples/python/main.py) + ## Quick Links - [Home](https://qpace.dev) diff --git a/lib/node/client.ts b/lib/node/client.ts index c3ce512..0bb88b6 100644 --- a/lib/node/client.ts +++ b/lib/node/client.ts @@ -4,7 +4,7 @@ import { version as VERSION, coreVersion as CORE_VERSION, } from "../../package.json"; -import { Timeframe, Sym } from "./index"; +import { type Timeframe, type Sym } from "./index"; // export const DEFAULT_REST_ENDPOINT = `http://0.0.0.0:3000/v1`; // export const DEFAULT_GRPC_ENDPOINT = `0.0.0.0:3001`; diff --git a/static/indicator_banner.png b/static/indicator_banner.png new file mode 100644 index 0000000000000000000000000000000000000000..ecdd03575b506d62dcb1b34f1967fa1216c12c20 GIT binary patch literal 153994 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 Date: Mon, 4 Aug 2025 12:44:55 +0200 Subject: [PATCH 4/5] 0.2.7 --- .github/workflows/cd.yaml | 24 ++++++++++++------------ package.json | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/cd.yaml b/.github/workflows/cd.yaml index c57b0df..7d1a2c8 100644 --- a/.github/workflows/cd.yaml +++ b/.github/workflows/cd.yaml @@ -1,18 +1,18 @@ name: CD -on: - workflow_dispatch: - inputs: - target: - description: "Triplet to build (linux-x64-gnu / win32-x64-msvc)" - required: false - type: string - # on: -# pull_request: -# push: -# branches: -# - master +# workflow_dispatch: +# inputs: +# target: +# description: "Triplet to build (linux-x64-gnu / win32-x64-msvc)" +# required: false +# type: string + +on: + pull_request: + push: + branches: + - master # workflow_run: # workflows: ["CI"] diff --git a/package.json b/package.json index e902ad3..03b462a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "qpace", - "version": "0.2.6", + "version": "0.2.7", "coreVersion": "0.2.7", "description": "📊 The Quant SDK for Python and Javascript. Written in Rust.", "keywords": [ From 7b5bc8c0be1fbb33084f11be5adb9ea0062d2053 Mon Sep 17 00:00:00 2001 From: xnerhu Date: Mon, 4 Aug 2025 13:34:34 +0200 Subject: [PATCH 5/5] fix --- lib/node/client.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/node/client.ts b/lib/node/client.ts index 0bb88b6..edb0b66 100644 --- a/lib/node/client.ts +++ b/lib/node/client.ts @@ -65,6 +65,7 @@ class SymClient { timeframe, }, }); + const { Sym } = require("./index"); return data["symbols"].map((r: any) => Sym.fromJSON(r)); } }