use serde::{self, Deserialize, Deserializer, Serializer};
use time::{Date, OffsetDateTime};
pub type AccountId = String;
pub type Symbol = String;
pub type Price = f64;
pub type Quantity = f64;
pub type Volume = f64;
pub type NumberString = String;
pub type CurrencyCode = String;
pub type OrderId = String;
pub type StrategyId = i64;
pub type OrderUpdateId = String;
pub type PositionId = String;
pub type StreamSessionId = String;
pub type IndicatorId = String;
pub type SubAccountId = String;
pub type Spread = String;
pub type MarketComplexType = String;
pub mod timestamp_ms {
use super::*;
pub fn serialize<S: Serializer>(dt: &OffsetDateTime, s: S) -> Result<S::Ok, S::Error> {
let ms = (dt.unix_timestamp_nanos() / 1_000_000) as i64;
s.serialize_i64(ms)
}
pub fn deserialize<'de, D: Deserializer<'de>>(d: D) -> Result<OffsetDateTime, D::Error> {
let ms = i64::deserialize(d)?;
OffsetDateTime::from_unix_timestamp_nanos(ms as i128 * 1_000_000)
.map_err(serde::de::Error::custom)
}
}
pub mod option_timestamp_ms {
use super::*;
pub fn serialize<S: Serializer>(dt: &Option<OffsetDateTime>, s: S) -> Result<S::Ok, S::Error> {
match dt {
Some(dt) => timestamp_ms::serialize(dt, s),
None => s.serialize_none(),
}
}
pub fn deserialize<'de, D: Deserializer<'de>>(
d: D,
) -> Result<Option<OffsetDateTime>, D::Error> {
let ms = Option::<i64>::deserialize(d)?;
match ms {
Some(ms) => OffsetDateTime::from_unix_timestamp_nanos(ms as i128 * 1_000_000)
.map(Some)
.map_err(serde::de::Error::custom),
None => Ok(None),
}
}
}
pub mod date_yyyymmdd {
use super::*;
use time::macros::format_description;
pub fn serialize<S: Serializer>(date: &Date, s: S) -> Result<S::Ok, S::Error> {
let fmt = format_description!("[year][month][day]");
s.serialize_str(&date.format(fmt).map_err(serde::ser::Error::custom)?)
}
pub fn deserialize<'de, D: Deserializer<'de>>(d: D) -> Result<Date, D::Error> {
let s = String::deserialize(d)?;
let fmt = format_description!("[year][month][day]");
Date::parse(&s, fmt).map_err(serde::de::Error::custom)
}
}
pub mod option_date_yyyymmdd {
use super::*;
pub fn serialize<S: Serializer>(date: &Option<Date>, s: S) -> Result<S::Ok, S::Error> {
match date {
Some(date) => date_yyyymmdd::serialize(date, s),
None => s.serialize_none(),
}
}
pub fn deserialize<'de, D: Deserializer<'de>>(d: D) -> Result<Option<Date>, D::Error> {
let s = Option::<String>::deserialize(d)?;
match s {
Some(s) if !s.is_empty() => {
let fmt = time::macros::format_description!("[year][month][day]");
Date::parse(&s, fmt)
.map(Some)
.map_err(serde::de::Error::custom)
}
_ => Ok(None),
}
}
}
pub mod option_datetime_rfc3339 {
use super::*;
use time::format_description::well_known::Rfc3339;
pub fn serialize<S: Serializer>(dt: &Option<OffsetDateTime>, s: S) -> Result<S::Ok, S::Error> {
match dt {
Some(dt) => s.serialize_str(&dt.format(&Rfc3339).map_err(serde::ser::Error::custom)?),
None => s.serialize_none(),
}
}
pub fn deserialize<'de, D: Deserializer<'de>>(
d: D,
) -> Result<Option<OffsetDateTime>, D::Error> {
let s = Option::<String>::deserialize(d)?;
match s {
Some(s) if !s.is_empty() => OffsetDateTime::parse(&s, &Rfc3339)
.map(Some)
.map_err(serde::de::Error::custom),
_ => Ok(None),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde::{Deserialize, Serialize};
use time::macros::{date, datetime};
#[derive(Debug, Serialize, Deserialize, PartialEq)]
struct TsTest {
#[serde(with = "timestamp_ms")]
ts: OffsetDateTime,
}
#[derive(Debug, Serialize, Deserialize, PartialEq)]
struct OptTsTest {
#[serde(default, with = "option_timestamp_ms")]
ts: Option<OffsetDateTime>,
}
#[derive(Debug, Serialize, Deserialize, PartialEq)]
struct DateTest {
#[serde(with = "date_yyyymmdd")]
d: Date,
}
#[derive(Debug, Serialize, Deserialize, PartialEq)]
struct OptDateTest {
#[serde(default, with = "option_date_yyyymmdd")]
d: Option<Date>,
}
#[derive(Debug, Serialize, Deserialize, PartialEq)]
struct OptRfc3339Test {
#[serde(default, with = "option_datetime_rfc3339")]
dt: Option<OffsetDateTime>,
}
#[test]
fn timestamp_ms_serde() {
let dt = datetime!(2024-01-15 12:30:00 UTC);
let t = TsTest { ts: dt };
let json = serde_json::to_string(&t).unwrap();
let parsed: TsTest = serde_json::from_str(&json).unwrap();
assert_eq!(parsed.ts, dt);
let parsed: TsTest = serde_json::from_str(r#"{"ts":1705322400000}"#).unwrap();
assert_eq!(parsed.ts, datetime!(2024-01-15 12:40:00 UTC));
let mut de = serde_json::Deserializer::from_str("1705322400000");
let dt = timestamp_ms::deserialize(&mut de).unwrap();
assert_eq!(dt, datetime!(2024-01-15 12:40:00 UTC));
let dt = datetime!(2024-01-15 12:40:00 UTC);
let mut buf = Vec::new();
let mut ser = serde_json::Serializer::new(&mut buf);
timestamp_ms::serialize(&dt, &mut ser).unwrap();
assert_eq!(String::from_utf8(buf).unwrap(), "1705322400000");
}
#[test]
fn option_timestamp_ms_serde() {
let parsed: OptTsTest = serde_json::from_str(r#"{"ts":1705322400000}"#).unwrap();
assert_eq!(parsed.ts, Some(datetime!(2024-01-15 12:40:00 UTC)));
let parsed: OptTsTest = serde_json::from_str(r#"{}"#).unwrap();
assert_eq!(parsed.ts, None);
let t = OptTsTest { ts: None };
let json = serde_json::to_string(&t).unwrap();
assert_eq!(json, r#"{"ts":null}"#);
let parsed: OptTsTest = serde_json::from_str(r#"{"ts":null}"#).unwrap();
assert_eq!(parsed.ts, None);
let dt = datetime!(2024-06-15 08:00:00 UTC);
let t = OptTsTest { ts: Some(dt) };
let json = serde_json::to_string(&t).unwrap();
let parsed: OptTsTest = serde_json::from_str(&json).unwrap();
assert_eq!(parsed.ts, Some(dt));
let mut de = serde_json::Deserializer::from_str("1705322400000");
let dt = option_timestamp_ms::deserialize(&mut de).unwrap();
assert_eq!(dt, Some(datetime!(2024-01-15 12:40:00 UTC)));
let dt = Some(datetime!(2024-06-15 08:00:00 UTC));
let mut buf = Vec::new();
let mut ser = serde_json::Serializer::new(&mut buf);
option_timestamp_ms::serialize(&dt, &mut ser).unwrap();
assert!(!String::from_utf8(buf).unwrap().is_empty());
}
#[test]
fn date_yyyymmdd_serde() {
let t = DateTest {
d: date!(2024 - 01 - 15),
};
let json = serde_json::to_string(&t).unwrap();
assert!(json.contains("20240115"));
let parsed: DateTest = serde_json::from_str(&json).unwrap();
assert_eq!(parsed.d, date!(2024 - 01 - 15));
let mut de = serde_json::Deserializer::from_str(r#""20240115""#);
let d = date_yyyymmdd::deserialize(&mut de).unwrap();
assert_eq!(d, date!(2024 - 01 - 15));
let d = date!(2024 - 01 - 15);
let mut buf = Vec::new();
let mut ser = serde_json::Serializer::new(&mut buf);
date_yyyymmdd::serialize(&d, &mut ser).unwrap();
assert!(String::from_utf8(buf).unwrap().contains("20240115"));
}
#[test]
fn option_date_yyyymmdd_serde() {
let parsed: OptDateTest = serde_json::from_str(r#"{"d":"20240115"}"#).unwrap();
assert_eq!(parsed.d, Some(date!(2024 - 01 - 15)));
let parsed: OptDateTest = serde_json::from_str(r#"{}"#).unwrap();
assert_eq!(parsed.d, None);
let parsed: OptDateTest = serde_json::from_str(r#"{"d":null}"#).unwrap();
assert_eq!(parsed.d, None);
let parsed: OptDateTest = serde_json::from_str(r#"{"d":""}"#).unwrap();
assert_eq!(parsed.d, None);
let json = serde_json::to_string(&OptDateTest { d: None }).unwrap();
assert_eq!(json, r#"{"d":null}"#);
let json = serde_json::to_string(&OptDateTest {
d: Some(date!(2024 - 03 - 15)),
})
.unwrap();
assert!(json.contains("20240315"));
let t = OptDateTest {
d: Some(date!(2024 - 06 - 15)),
};
let parsed: OptDateTest =
serde_json::from_str(&serde_json::to_string(&t).unwrap()).unwrap();
assert_eq!(parsed, t);
let mut de = serde_json::Deserializer::from_str(r#""20240315""#);
let d = option_date_yyyymmdd::deserialize(&mut de).unwrap();
assert_eq!(d, Some(date!(2024 - 03 - 15)));
}
#[test]
fn option_datetime_rfc3339_serde() {
let parsed: OptRfc3339Test =
serde_json::from_str(r#"{"dt":"2016-08-01T00:00:00Z"}"#).unwrap();
assert_eq!(parsed.dt, Some(datetime!(2016-08-01 00:00:00 UTC)));
let parsed: OptRfc3339Test = serde_json::from_str(r#"{}"#).unwrap();
assert_eq!(parsed.dt, None);
let parsed: OptRfc3339Test = serde_json::from_str(r#"{"dt":""}"#).unwrap();
assert_eq!(parsed.dt, None);
let json = serde_json::to_string(&OptRfc3339Test { dt: None }).unwrap();
assert_eq!(json, r#"{"dt":null}"#);
let t = OptRfc3339Test {
dt: Some(datetime!(2024-01-15 12:30:00 UTC)),
};
let json = serde_json::to_string(&t).unwrap();
assert!(json.contains("2024-01-15T12:30:00Z"));
let parsed: OptRfc3339Test = serde_json::from_str(&json).unwrap();
assert_eq!(parsed, t);
let mut de = serde_json::Deserializer::from_str(r#""2024-01-15T12:30:00Z""#);
let dt = option_datetime_rfc3339::deserialize(&mut de).unwrap();
assert_eq!(dt, Some(datetime!(2024-01-15 12:30:00 UTC)));
let dt = Some(datetime!(2024-01-15 12:30:00 UTC));
let mut buf = Vec::new();
let mut ser = serde_json::Serializer::new(&mut buf);
option_datetime_rfc3339::serialize(&dt, &mut ser).unwrap();
assert!(String::from_utf8(buf).unwrap().contains("2024-01-15"));
}
}