@@ -24,13 +24,13 @@ build:
|
|||||||
script:
|
script:
|
||||||
- cargo +nightly build
|
- cargo +nightly build
|
||||||
|
|
||||||
# test:
|
test:
|
||||||
# image: registry.karaolidis.com/karaolidis/qrust/rust
|
image: registry.karaolidis.com/karaolidis/qrust/rust
|
||||||
# stage: test
|
stage: test
|
||||||
# cache:
|
cache:
|
||||||
# <<: *global_cache
|
<<: *global_cache
|
||||||
# script:
|
script:
|
||||||
# - cargo +nightly test
|
- cargo +nightly test
|
||||||
|
|
||||||
lint:
|
lint:
|
||||||
image: registry.karaolidis.com/karaolidis/qrust/rust
|
image: registry.karaolidis.com/karaolidis/qrust/rust
|
||||||
|
102
Cargo.lock
generated
102
Cargo.lock
generated
@@ -19,9 +19,9 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aho-corasick"
|
name = "aho-corasick"
|
||||||
version = "1.1.2"
|
version = "1.1.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
|
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
@@ -55,13 +55,13 @@ checksum = "7b3d0060af21e8d11a926981cc00c6c1541aa91dd64b9f881985c3da1094425f"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-trait"
|
name = "async-trait"
|
||||||
version = "0.1.77"
|
version = "0.1.78"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9"
|
checksum = "461abc97219de0eaaf81fe3ef974a540158f3d079c2ab200f891f1a2ef201e85"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.52",
|
"syn 2.0.53",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -168,9 +168,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "2.4.2"
|
version = "2.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf"
|
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "block-buffer"
|
name = "block-buffer"
|
||||||
@@ -233,6 +233,15 @@ dependencies = [
|
|||||||
"windows-targets 0.52.4",
|
"windows-targets 0.52.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "claims"
|
||||||
|
version = "0.7.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b6995bbe186456c36307f8ea36be3eefe42f49d106896414e18efc4fb2f846b5"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clickhouse"
|
name = "clickhouse"
|
||||||
version = "0.11.6"
|
version = "0.11.6"
|
||||||
@@ -342,7 +351,7 @@ dependencies = [
|
|||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"strsim",
|
"strsim",
|
||||||
"syn 2.0.52",
|
"syn 2.0.53",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -353,7 +362,7 @@ checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"darling_core",
|
"darling_core",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.52",
|
"syn 2.0.53",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -541,7 +550,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.52",
|
"syn 2.0.53",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -629,9 +638,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "h2"
|
name = "h2"
|
||||||
version = "0.3.24"
|
version = "0.3.25"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9"
|
checksum = "4fbd2820c5e49886948654ab546d0688ff24530286bdcf8fca3cefb16d4618eb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"fnv",
|
"fnv",
|
||||||
@@ -648,9 +657,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "h2"
|
name = "h2"
|
||||||
version = "0.4.2"
|
version = "0.4.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "31d030e59af851932b72ceebadf4a2b5986dba4c3b99dd2493f8273a0f151943"
|
checksum = "51ee2dd2e4f378392eeff5d51618cd9a63166a2513846bbc55f21cfacd9199d4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"fnv",
|
"fnv",
|
||||||
@@ -782,7 +791,7 @@ dependencies = [
|
|||||||
"futures-channel",
|
"futures-channel",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"h2 0.3.24",
|
"h2 0.3.25",
|
||||||
"http 0.2.12",
|
"http 0.2.12",
|
||||||
"http-body 0.4.6",
|
"http-body 0.4.6",
|
||||||
"httparse",
|
"httparse",
|
||||||
@@ -805,7 +814,7 @@ dependencies = [
|
|||||||
"bytes",
|
"bytes",
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"h2 0.4.2",
|
"h2 0.4.3",
|
||||||
"http 1.1.0",
|
"http 1.1.0",
|
||||||
"http-body 1.0.0",
|
"http-body 1.0.0",
|
||||||
"httparse",
|
"httparse",
|
||||||
@@ -1168,7 +1177,7 @@ version = "0.10.64"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f"
|
checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.4.2",
|
"bitflags 2.5.0",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"foreign-types",
|
"foreign-types",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -1185,7 +1194,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.52",
|
"syn 2.0.53",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1261,7 +1270,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.52",
|
"syn 2.0.53",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1316,6 +1325,7 @@ dependencies = [
|
|||||||
"async-trait",
|
"async-trait",
|
||||||
"axum",
|
"axum",
|
||||||
"backoff",
|
"backoff",
|
||||||
|
"claims",
|
||||||
"clickhouse",
|
"clickhouse",
|
||||||
"dotenv",
|
"dotenv",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
@@ -1332,6 +1342,7 @@ dependencies = [
|
|||||||
"serde-aux",
|
"serde-aux",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_repr",
|
"serde_repr",
|
||||||
|
"serde_test",
|
||||||
"serde_with",
|
"serde_with",
|
||||||
"time",
|
"time",
|
||||||
"tokio",
|
"tokio",
|
||||||
@@ -1399,7 +1410,7 @@ version = "11.0.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9d86a7c4638d42c44551f4791a20e687dbb4c3de1f33c43dd71e355cd429def1"
|
checksum = "9d86a7c4638d42c44551f4791a20e687dbb4c3de1f33c43dd71e355cd429def1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.4.2",
|
"bitflags 2.5.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1442,16 +1453,16 @@ checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "reqwest"
|
name = "reqwest"
|
||||||
version = "0.11.26"
|
version = "0.11.27"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "78bf93c4af7a8bb7d879d51cebe797356ff10ae8516ace542b5182d9dcac10b2"
|
checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
"bytes",
|
"bytes",
|
||||||
"encoding_rs",
|
"encoding_rs",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"h2 0.3.24",
|
"h2 0.3.25",
|
||||||
"http 0.2.12",
|
"http 0.2.12",
|
||||||
"http-body 0.4.6",
|
"http-body 0.4.6",
|
||||||
"hyper 0.14.28",
|
"hyper 0.14.28",
|
||||||
@@ -1488,11 +1499,11 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustix"
|
name = "rustix"
|
||||||
version = "0.38.31"
|
version = "0.38.32"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949"
|
checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.4.2",
|
"bitflags 2.5.0",
|
||||||
"errno",
|
"errno",
|
||||||
"libc",
|
"libc",
|
||||||
"linux-raw-sys",
|
"linux-raw-sys",
|
||||||
@@ -1608,7 +1619,7 @@ checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.52",
|
"syn 2.0.53",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1651,7 +1662,16 @@ checksum = "0b2e6b945e9d3df726b65d6ee24060aff8e3533d431f677a9695db04eff9dfdb"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.52",
|
"syn 2.0.53",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_test"
|
||||||
|
version = "1.0.176"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5a2f49ace1498612d14f7e0b8245519584db8299541dfe31a06374a828d620ab"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1693,14 +1713,14 @@ dependencies = [
|
|||||||
"darling",
|
"darling",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.52",
|
"syn 2.0.53",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_yaml"
|
name = "serde_yaml"
|
||||||
version = "0.9.32"
|
version = "0.9.33"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8fd075d994154d4a774f95b51fb96bdc2832b0ea48425c92546073816cda1f2f"
|
checksum = "a0623d197252096520c6f2a5e1171ee436e5af99a5d7caa2891e55e61950e6d9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap 2.2.5",
|
"indexmap 2.2.5",
|
||||||
"itoa",
|
"itoa",
|
||||||
@@ -1790,9 +1810,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.52"
|
version = "2.0.53"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07"
|
checksum = "7383cd0e49fff4b6b90ca5670bfd3e9d6a733b3f90c686605aa7eec8c4996032"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -1855,7 +1875,7 @@ checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.52",
|
"syn 2.0.53",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1941,7 +1961,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.52",
|
"syn 2.0.53",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2109,9 +2129,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unsafe-libyaml"
|
name = "unsafe-libyaml"
|
||||||
version = "0.2.10"
|
version = "0.2.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ab4c90930b95a82d00dc9e9ac071b4991924390d46cbd0dfe566148667605e4b"
|
checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "url"
|
name = "url"
|
||||||
@@ -2132,9 +2152,9 @@ checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uuid"
|
name = "uuid"
|
||||||
version = "1.7.0"
|
version = "1.8.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a"
|
checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"getrandom",
|
"getrandom",
|
||||||
"serde",
|
"serde",
|
||||||
@@ -2188,7 +2208,7 @@ dependencies = [
|
|||||||
"once_cell",
|
"once_cell",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.52",
|
"syn 2.0.53",
|
||||||
"wasm-bindgen-shared",
|
"wasm-bindgen-shared",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -2222,7 +2242,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.52",
|
"syn 2.0.53",
|
||||||
"wasm-bindgen-backend",
|
"wasm-bindgen-backend",
|
||||||
"wasm-bindgen-shared",
|
"wasm-bindgen-shared",
|
||||||
]
|
]
|
||||||
|
@@ -71,3 +71,7 @@ lazy_static = "1.4.0"
|
|||||||
nonempty = { version = "0.10.0", features = [
|
nonempty = { version = "0.10.0", features = [
|
||||||
"serialize",
|
"serialize",
|
||||||
] }
|
] }
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
claims = "0.7.1"
|
||||||
|
serde_test = "1.0.176"
|
||||||
|
@@ -13,3 +13,14 @@ pub fn strip(content: &str) -> String {
|
|||||||
let content = content.trim();
|
let content = content.trim();
|
||||||
content.to_string()
|
content.to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_strip() {
|
||||||
|
let content = "<p> <b> Hello, </b> <i> World! </i> </p>";
|
||||||
|
assert_eq!(strip(content), "Hello, World!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -223,3 +223,53 @@ impl Order {
|
|||||||
orders
|
orders
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_normalize() {
|
||||||
|
let order_template = Order {
|
||||||
|
id: Uuid::new_v4(),
|
||||||
|
client_order_id: Uuid::new_v4(),
|
||||||
|
created_at: OffsetDateTime::now_utc(),
|
||||||
|
updated_at: None,
|
||||||
|
submitted_at: OffsetDateTime::now_utc(),
|
||||||
|
filled_at: None,
|
||||||
|
expired_at: None,
|
||||||
|
cancel_requested_at: None,
|
||||||
|
canceled_at: None,
|
||||||
|
failed_at: None,
|
||||||
|
replaced_at: None,
|
||||||
|
replaced_by: None,
|
||||||
|
replaces: None,
|
||||||
|
asset_id: Uuid::new_v4(),
|
||||||
|
symbol: "AAPL".to_string(),
|
||||||
|
asset_class: super::super::asset::Class::UsEquity,
|
||||||
|
notional: None,
|
||||||
|
qty: None,
|
||||||
|
filled_qty: 0.0,
|
||||||
|
filled_avg_price: None,
|
||||||
|
order_class: Class::Simple,
|
||||||
|
order_type: Type::Market,
|
||||||
|
side: Side::Buy,
|
||||||
|
time_in_force: TimeInForce::Day,
|
||||||
|
limit_price: None,
|
||||||
|
stop_price: None,
|
||||||
|
status: Status::New,
|
||||||
|
extended_hours: false,
|
||||||
|
legs: None,
|
||||||
|
trail_percent: None,
|
||||||
|
trail_price: None,
|
||||||
|
hwm: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut order = order_template.clone();
|
||||||
|
order.legs = Some(vec![order_template.clone(), order_template.clone()]);
|
||||||
|
order.legs.as_mut().unwrap()[0].legs = Some(vec![order_template.clone()]);
|
||||||
|
let orders = order.normalize();
|
||||||
|
|
||||||
|
assert_eq!(orders.len(), 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -86,7 +86,7 @@ where
|
|||||||
struct TimeVisitor;
|
struct TimeVisitor;
|
||||||
|
|
||||||
impl<'de> Visitor<'de> for TimeVisitor {
|
impl<'de> Visitor<'de> for TimeVisitor {
|
||||||
type Value = time::Time;
|
type Value = Time;
|
||||||
|
|
||||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
formatter.write_str("a string in the format HH:MM")
|
formatter.write_str("a string in the format HH:MM")
|
||||||
@@ -102,3 +102,92 @@ where
|
|||||||
|
|
||||||
deserializer.deserialize_str(TimeVisitor)
|
deserializer.deserialize_str(TimeVisitor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use serde::Deserialize;
|
||||||
|
use serde_test::{assert_de_tokens, Token};
|
||||||
|
use time::Time;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_add_slash() {
|
||||||
|
assert_eq!(add_slash("BTCUSD"), "BTC/USD");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_add_slash_skip() {
|
||||||
|
assert_eq!(add_slash("ABTC"), "ABTC");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Debug, Deserialize)]
|
||||||
|
#[serde(transparent)]
|
||||||
|
struct AddSlashToSymbol {
|
||||||
|
#[serde(deserialize_with = "add_slash_to_symbol")]
|
||||||
|
symbol: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_add_slash_to_symbol() {
|
||||||
|
assert_de_tokens::<AddSlashToSymbol>(
|
||||||
|
&AddSlashToSymbol {
|
||||||
|
symbol: String::from("BTC/USD"),
|
||||||
|
},
|
||||||
|
&[Token::Str("BTCUSD")],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_add_slash_to_symbol_skip() {
|
||||||
|
assert_de_tokens::<AddSlashToSymbol>(
|
||||||
|
&AddSlashToSymbol {
|
||||||
|
symbol: String::from("ABTC"),
|
||||||
|
},
|
||||||
|
&[Token::Str("ABTC")],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Debug, Deserialize)]
|
||||||
|
#[serde(transparent)]
|
||||||
|
struct AddSlashToSymbols {
|
||||||
|
#[serde(deserialize_with = "add_slash_to_symbols")]
|
||||||
|
symbols: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_add_slash_to_symbols() {
|
||||||
|
assert_de_tokens::<AddSlashToSymbols>(
|
||||||
|
&AddSlashToSymbols {
|
||||||
|
symbols: vec![
|
||||||
|
String::from("BTC/USD"),
|
||||||
|
String::from("ETH/USD"),
|
||||||
|
String::from("ABTC"),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
&[
|
||||||
|
Token::Seq { len: Some(3) },
|
||||||
|
Token::Str("BTCUSD"),
|
||||||
|
Token::Str("ETHUSD"),
|
||||||
|
Token::Str("ABTC"),
|
||||||
|
Token::SeqEnd,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Debug, Deserialize)]
|
||||||
|
#[serde(transparent)]
|
||||||
|
struct HumanTime {
|
||||||
|
#[serde(deserialize_with = "human_time_hh_mm")]
|
||||||
|
time: Time,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_human_time_hh_mm() {
|
||||||
|
assert_de_tokens::<HumanTime>(
|
||||||
|
&HumanTime {
|
||||||
|
time: Time::from_hms(12, 34, 0).unwrap(),
|
||||||
|
},
|
||||||
|
&[Token::Str("12:34")],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -5,27 +5,48 @@ pub fn timeframe<S>(timeframe: &Duration, serializer: S) -> Result<S::Ok, S::Err
|
|||||||
where
|
where
|
||||||
S: serde::Serializer,
|
S: serde::Serializer,
|
||||||
{
|
{
|
||||||
let mins = timeframe.as_secs() / 60;
|
let secs = timeframe.as_secs();
|
||||||
|
|
||||||
|
if secs < 60 || secs % 60 != 0 {
|
||||||
|
return Err(serde::ser::Error::custom("Invalid timeframe duration"));
|
||||||
|
}
|
||||||
|
|
||||||
|
let mins = secs / 60;
|
||||||
|
|
||||||
if mins < 60 {
|
if mins < 60 {
|
||||||
return serializer.serialize_str(&format!("{mins}Min"));
|
return serializer.serialize_str(&format!("{mins}Min"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if mins % 60 != 0 {
|
||||||
|
return Err(serde::ser::Error::custom("Invalid timeframe duration"));
|
||||||
|
}
|
||||||
|
|
||||||
let hours = mins / 60;
|
let hours = mins / 60;
|
||||||
|
|
||||||
if hours < 24 {
|
if hours < 24 {
|
||||||
return serializer.serialize_str(&format!("{hours}Hour"));
|
return serializer.serialize_str(&format!("{hours}Hour"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if hours % 24 != 0 {
|
||||||
|
return Err(serde::ser::Error::custom("Invalid timeframe duration"));
|
||||||
|
}
|
||||||
|
|
||||||
let days = hours / 24;
|
let days = hours / 24;
|
||||||
|
|
||||||
if days == 1 {
|
if days == 1 {
|
||||||
return serializer.serialize_str("1Day");
|
return serializer.serialize_str("1Day");
|
||||||
}
|
}
|
||||||
|
|
||||||
let weeks = days / 7;
|
if days == 7 {
|
||||||
if weeks == 1 {
|
|
||||||
return serializer.serialize_str("1Week");
|
return serializer.serialize_str("1Week");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if days < 30 || days % 30 != 0 {
|
||||||
|
return Err(serde::ser::Error::custom("Invalid timeframe duration"));
|
||||||
|
}
|
||||||
|
|
||||||
let months = days / 30;
|
let months = days / 30;
|
||||||
|
|
||||||
if [1, 2, 3, 4, 6, 12].contains(&months) {
|
if [1, 2, 3, 4, 6, 12].contains(&months) {
|
||||||
return serializer.serialize_str(&format!("{months}Month"));
|
return serializer.serialize_str(&format!("{months}Month"));
|
||||||
};
|
};
|
||||||
@@ -87,3 +108,174 @@ where
|
|||||||
|
|
||||||
join_symbols(&symbols, serializer)
|
join_symbols(&symbols, serializer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use serde::Serialize;
|
||||||
|
use serde_test::{assert_ser_tokens, assert_ser_tokens_error, Token};
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
#[serde(transparent)]
|
||||||
|
struct Timeframe {
|
||||||
|
#[serde(serialize_with = "timeframe")]
|
||||||
|
duration: Duration,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_timeframe_30_mins() {
|
||||||
|
let timeframe = Timeframe {
|
||||||
|
duration: Duration::from_secs(60 * 30),
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_ser_tokens(&timeframe, &[Token::Str("30Min")]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_timeframe_2_hours() {
|
||||||
|
let timeframe = Timeframe {
|
||||||
|
duration: Duration::from_secs(60 * 60 * 2),
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_ser_tokens(&timeframe, &[Token::Str("2Hour")]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_timeframe_1_day() {
|
||||||
|
let timeframe = Timeframe {
|
||||||
|
duration: Duration::from_secs(60 * 60 * 24),
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_ser_tokens(&timeframe, &[Token::Str("1Day")]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_timeframe_1_week() {
|
||||||
|
let timeframe = Timeframe {
|
||||||
|
duration: Duration::from_secs(60 * 60 * 24 * 7),
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_ser_tokens(&timeframe, &[Token::Str("1Week")]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_timeframe_6_months() {
|
||||||
|
let timeframe = Timeframe {
|
||||||
|
duration: Duration::from_secs(60 * 60 * 24 * 30 * 6),
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_ser_tokens(&timeframe, &[Token::Str("6Month")]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_timeframe_invalid_1_second() {
|
||||||
|
let timeframe = Timeframe {
|
||||||
|
duration: Duration::from_secs(1),
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_ser_tokens_error(&timeframe, &[], "Invalid timeframe duration");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_timeframe_invalid_61_seconds() {
|
||||||
|
let timeframe = Timeframe {
|
||||||
|
duration: Duration::from_secs(61),
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_ser_tokens_error(&timeframe, &[], "Invalid timeframe duration");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_timeframe_invalid_6_days() {
|
||||||
|
let timeframe = Timeframe {
|
||||||
|
duration: Duration::from_secs(60 * 60 * 24 * 6),
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_ser_tokens_error(&timeframe, &[], "Invalid timeframe duration");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_remove_slash() {
|
||||||
|
let pair = "BTC/USDT";
|
||||||
|
assert_eq!(remove_slash(pair), "BTCUSDT");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
#[serde(transparent)]
|
||||||
|
struct JoinSymbols {
|
||||||
|
#[serde(serialize_with = "join_symbols")]
|
||||||
|
symbols: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_join_symbols() {
|
||||||
|
let symbols = JoinSymbols {
|
||||||
|
symbols: vec![String::from("BTC/USD"), String::from("ETH/USD")],
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_ser_tokens(&symbols, &[Token::Str("BTC/USD,ETH/USD")]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
#[serde(transparent)]
|
||||||
|
struct JoinSymbolsOption {
|
||||||
|
#[serde(serialize_with = "join_symbols_option")]
|
||||||
|
symbols: Option<Vec<String>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_join_symbols_option_some() {
|
||||||
|
let symbols = JoinSymbolsOption {
|
||||||
|
symbols: Some(vec![String::from("BTC/USD"), String::from("ETH/USD")]),
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_ser_tokens(&symbols, &[Token::Str("BTC/USD,ETH/USD")]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_join_symbols_option_none() {
|
||||||
|
let symbols = JoinSymbolsOption { symbols: None };
|
||||||
|
|
||||||
|
assert_ser_tokens(&symbols, &[Token::None]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
#[serde(transparent)]
|
||||||
|
struct RemoveSlashFromSymbols {
|
||||||
|
#[serde(serialize_with = "remove_slash_from_symbols")]
|
||||||
|
symbols: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_remove_slash_from_symbols() {
|
||||||
|
let symbols = RemoveSlashFromSymbols {
|
||||||
|
symbols: vec![String::from("BTC/USD"), String::from("ETH/USD")],
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_ser_tokens(
|
||||||
|
&symbols,
|
||||||
|
&[
|
||||||
|
Token::Seq { len: Some(2) },
|
||||||
|
Token::Str("BTCUSD"),
|
||||||
|
Token::Str("ETHUSD"),
|
||||||
|
Token::SeqEnd,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
#[serde(transparent)]
|
||||||
|
struct RemoveSlashAndJoinSymbols {
|
||||||
|
#[serde(serialize_with = "remove_slash_and_join_symbols")]
|
||||||
|
symbols: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_remove_slash_and_join_symbols() {
|
||||||
|
let symbols = RemoveSlashAndJoinSymbols {
|
||||||
|
symbols: vec![String::from("BTC/USD"), String::from("ETH/USD")],
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_ser_tokens(&symbols, &[Token::Str("BTCUSD,ETHUSD")]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -26,3 +26,21 @@ pub fn duration_until(time: OffsetDateTime) -> Duration {
|
|||||||
Duration::default()
|
Duration::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_duration_until_future() {
|
||||||
|
let future = OffsetDateTime::now_utc() + Duration::from_secs(60);
|
||||||
|
let duration = duration_until(future).as_secs();
|
||||||
|
assert!((59..=61).contains(&duration));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_duration_until_past() {
|
||||||
|
let past = OffsetDateTime::now_utc() - Duration::from_secs(60);
|
||||||
|
assert_eq!(duration_until(past).as_secs(), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user