Skip to content

Commit acfc78e

Browse files
committed
xd
1 parent 3f9079b commit acfc78e

36 files changed

+739
-3530
lines changed

Cargo.lock

Lines changed: 0 additions & 13 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
</div>
1111

12-
**qPACE**: The Technical Analysis framework for Python and JavaScript, written in Rust, designed to be extremely fast. Everything you need in one place.
12+
**qPACE**: The Technical Analysis framework for Python and JavaScript, written in Rust, designed to be extremely fast. Everything you need in one place - from research to production.
1313

1414
![backtest summary](/static/backtest_summary.png)
1515

core/ohlcv.rs

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -398,23 +398,40 @@ pub fn zip_ohlcv_bars(
398398
return bars;
399399
}
400400

401-
cfg_if::cfg_if! { if #[cfg(feature = "bindings_wasm")] {
402-
#[wasm_bindgen(js_name=zipOhlcvBars)]
403-
#[inline]
404-
pub fn js_zip_ohlcv_bars(
405-
open_time: Option<Vec<js_sys::Date>>,
406-
close_time: Option<Vec<js_sys::Date>>,
407-
open: Option<Vec<f64>>,
408-
high: Option<Vec<f64>>,
409-
low: Option<Vec<f64>>,
410-
close: Option<Vec<f64>>,
411-
volume: Option<Vec<f64>>,
412-
) -> Vec<OhlcvBar> {
413-
let open_time = open_time.map(|list| list.iter().map(|x| Some(DateTime::from(x))).collect::<Vec<_>>());
414-
let close_time = close_time.map(|list| list.iter().map(|x| Some(DateTime::from(x))).collect::<Vec<_>>());
415-
zip_ohlcv_bars(open_time, close_time, open, high, low, close, volume)
416-
}
417-
}}
401+
#[cfg(feature = "bindings_wasm")]
402+
#[wasm_bindgen(js_name=zipOhlcvBars)]
403+
#[inline]
404+
pub fn js_zip_ohlcv_bars(
405+
open_time: Option<Vec<js_sys::Date>>,
406+
close_time: Option<Vec<js_sys::Date>>,
407+
open: Option<Vec<f64>>,
408+
high: Option<Vec<f64>>,
409+
low: Option<Vec<f64>>,
410+
close: Option<Vec<f64>>,
411+
volume: Option<Vec<f64>>,
412+
) -> Vec<OhlcvBar> {
413+
let open_time = open_time.map(|list| {
414+
list.iter()
415+
.map(|x| Some(DateTime::from(x)))
416+
.collect::<Vec<_>>()
417+
});
418+
let close_time = close_time.map(|list| {
419+
list.iter()
420+
.map(|x| Some(DateTime::from(x)))
421+
.collect::<Vec<_>>()
422+
});
423+
zip_ohlcv_bars(open_time, close_time, open, high, low, close, volume)
424+
}
425+
426+
// implement unzip for js
427+
// #[cfg(feature = "bindings_wasm")]
428+
// #[wasm_bindgen(js_name=unzipOhlcvBars)]
429+
// #[inline]
430+
// pub fn js_unzip_ohlcv_bars(bars: Vec<OhlcvBar>) -> Vec<Vec<Option<js_sys::Date>>> {
431+
// let open_time = bars.iter().map(|bar| Some(js_sys::Date::new(&bar.open_time.to_string()))).collect::<Vec<_>>();
432+
// let close_time = bars.iter().map(|bar| Some(js_sys::Date::new(&bar.close_time.to_string()))).collect::<Vec<_>>();
433+
// vec![open_time, close_time]
434+
// }
418435

419436
cfg_if::cfg_if! { if #[cfg(feature = "polars")] {
420437
#[inline]

core/ohlcv_js.rs

Lines changed: 83 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ cfg_if::cfg_if! { if #[cfg(feature = "bindings_wasm")] {
22
use wasm_bindgen::prelude::*;
33
use js_sys::{Object, Reflect};
44
use crate::timeframe_js::{JsTimeframe};
5+
use js_sys::Float64Array;
6+
use js_sys::Array;
57
}}
68
use crate::ohlcv::{zip_ohlcv_bars, Ohlcv};
79
use crate::timeframe::Timeframe;
@@ -16,6 +18,16 @@ use std::rc::Rc;
1618
use std::sync::{Arc, RwLock};
1719
use std::{ffi::OsStr, ops::Range, path::Path};
1820

21+
#[cfg(feature = "bindings_wasm")]
22+
#[wasm_bindgen(raw_module = "../../lib/internal.js")]
23+
extern "C" {
24+
#[wasm_bindgen(js_name = readOhlcvBarsFromPath)]
25+
fn js_read_ohlcv_bars_from_path(format: &str, path: &str, time_unit: &str) -> Vec<OhlcvBar>;
26+
27+
#[wasm_bindgen(js_name = writeOhlcvBarsToPath)]
28+
fn js_write_ohlcv_bars_to_path(format: &str, path: &str, bars: Vec<OhlcvBar>);
29+
}
30+
1931
#[cfg(feature = "bindings_wasm")]
2032
#[wasm_bindgen(js_class=OhlcvBar)]
2133
impl OhlcvBar {
@@ -127,12 +139,12 @@ impl OhlcvBar {
127139
let obj = Object::new();
128140
let _ = Reflect::set(
129141
&obj,
130-
&"openTime".into(),
142+
&"open_time".into(),
131143
&JsValue::from(self.js_open_time()),
132144
);
133145
let _ = Reflect::set(
134146
&obj,
135-
&"closeTime".into(),
147+
&"close_time".into(),
136148
&JsValue::from(self.js_close_time()),
137149
);
138150
let _ = Reflect::set(&obj, &"open".into(), &JsValue::from(self.js_open()));
@@ -142,6 +154,43 @@ impl OhlcvBar {
142154
let _ = Reflect::set(&obj, &"volume".into(), &JsValue::from(self.js_volume()));
143155
obj.into()
144156
}
157+
158+
#[wasm_bindgen(js_name = "fromJSON")]
159+
pub fn js_from_json(json: JsValue) -> Self {
160+
let obj = json.unchecked_into::<Object>();
161+
let open_time = Reflect::get(&obj, &"open_time".into())
162+
.unwrap()
163+
.unchecked_into::<js_sys::Date>();
164+
let close_time = Reflect::get(&obj, &"close_time".into())
165+
.unwrap()
166+
.unchecked_into::<js_sys::Date>();
167+
let open = Reflect::get(&obj, &"open".into())
168+
.unwrap()
169+
.as_f64()
170+
.unwrap();
171+
let high = Reflect::get(&obj, &"high".into())
172+
.unwrap()
173+
.as_f64()
174+
.unwrap();
175+
let low = Reflect::get(&obj, &"low".into()).unwrap().as_f64().unwrap();
176+
let close = Reflect::get(&obj, &"close".into())
177+
.unwrap()
178+
.as_f64()
179+
.unwrap();
180+
let volume = Reflect::get(&obj, &"volume".into())
181+
.unwrap()
182+
.as_f64()
183+
.unwrap();
184+
Self::new(
185+
open_time.into(),
186+
close_time.into(),
187+
open,
188+
high,
189+
low,
190+
close,
191+
volume,
192+
)
193+
}
145194
}
146195

147196
#[cfg(feature = "bindings_wasm")]
@@ -343,4 +392,36 @@ impl JsOhlcv {
343392
pub fn js_add_many(&mut self, bars: Vec<OhlcvBar>) {
344393
self.push_many(&bars);
345394
}
395+
396+
#[wasm_bindgen(js_name = "readCSV")]
397+
#[inline]
398+
#[doc = "`time_unit: 'ms' | 's`. Default: 'ms'"]
399+
pub fn js_read_csv(path: &str, time_unit: Option<String>) -> JsOhlcv {
400+
let time_unit = time_unit.unwrap_or("ms".to_string());
401+
let bars = js_read_ohlcv_bars_from_path("csv", path, &time_unit);
402+
Ohlcv::from_bars(bars).into()
403+
}
404+
405+
#[wasm_bindgen(js_name = "readParquet")]
406+
#[inline]
407+
#[doc = "`time_unit: 'ms' | 's`. Default: 'ms'"]
408+
pub fn js_read_parquet(path: &str, time_unit: Option<String>) -> JsOhlcv {
409+
let time_unit = time_unit.unwrap_or("ms".to_string());
410+
let bars = js_read_ohlcv_bars_from_path("parquet", path, &time_unit);
411+
Ohlcv::from_bars(bars).into()
412+
}
413+
414+
#[wasm_bindgen(js_name = "writeCSV")]
415+
#[inline]
416+
pub fn js_write_csv(&self, path: &str) {
417+
let bars = self.all_bars();
418+
js_write_ohlcv_bars_to_path("csv", path, bars.to_vec());
419+
}
420+
421+
#[wasm_bindgen(js_name = "writeParquet")]
422+
#[inline]
423+
pub fn js_write_parquet(&self, path: &str) {
424+
let bars = self.all_bars();
425+
js_write_ohlcv_bars_to_path("parquet", path, bars.to_vec());
426+
}
346427
}

core/ohlcv_py.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,22 @@ impl OhlcvBar {
145145
dict.set_item("volume", self.volume())?;
146146
return Ok(dict.to_object(py));
147147
}
148+
149+
// #[pyo3(name = "from_dict")]
150+
// #[inline]
151+
// pub fn py_from_dict(py: Python<'_>, dict: PyDict) -> PyResult<OhlcvBar> {
152+
// let open_time = dict.get_item("open_time").and_then(|x| x.extract().ok());
153+
// let close_time = dict.get_item("close_time").and_then(|x| x.extract().ok());
154+
// let open = dict.get_item("open").and_then(|x| x.extract().ok());
155+
// let high = dict.get_item("high").and_then(|x| x.extract().ok());
156+
// let low = dict.get_item("low").and_then(|x| x.extract().ok());
157+
// let close = dict.get_item("close").and_then(|x| x.extract().ok());
158+
// let volume = dict.get_item("volume").and_then(|x| x.extract().ok());
159+
160+
// Ok(OhlcvBar::new(
161+
// open_time, close_time, open, high, low, close, volume,
162+
// ))
163+
// }
148164
}
149165

150166
#[cfg(feature = "bindings_py")]

0 commit comments

Comments
 (0)