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..ba6bd27 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1805,7 +1805,7 @@ version = "0.0.1-dev.1" [[package]] name = "qpace_core" -version = "0.2.6" +version = "0.2.7" dependencies = [ "cfg-if", "chrono", 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/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 1f6fef0..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, rfr: f64) -> f64 { - sortino_ratio_from_returns(&self.returns_list(), rfr) + 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 expectancy(&self) -> f64 { + expectancy(&self.pnl_list()) } #[inline] @@ -411,8 +444,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 +472,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 +699,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 { @@ -801,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("%"); @@ -830,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![ @@ -888,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/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/node/client.ts b/lib/node/client.ts index d197927..edb0b66 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 { 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`; @@ -19,11 +20,63 @@ 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, + }, + }); + const { Sym } = require("./index"); + 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 +95,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 +114,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 +125,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/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) diff --git a/package.json b/package.json index 74b4aa2..03b462a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "qpace", - "version": "0.2.6", - "coreVersion": "0.2.6", + "version": "0.2.7", + "coreVersion": "0.2.7", "description": "📊 The Quant SDK for Python and Javascript. Written in Rust.", "keywords": [ "quant", diff --git a/static/indicator_banner.png b/static/indicator_banner.png new file mode 100644 index 0000000..ecdd035 Binary files /dev/null and b/static/indicator_banner.png differ