From 66c2499520a6f5342910626a7c3784269b8b8ffc Mon Sep 17 00:00:00 2001 From: Sunli Date: Tue, 24 Dec 2024 12:15:14 +0800 Subject: [PATCH] add support for more candlesticks periods --- c/csrc/include/longport.h | 46 ++++++- c/src/quote_context/enum_types.rs | 37 ++++- cpp/include/types.hpp | 30 +++- cpp/src/convert.hpp | 34 +++++ .../main/java/com/longport/quote/Period.java | 9 ++ java/src/types/enum_types.rs | 20 ++- nodejs/src/quote/types.rs | 39 +++++- python/src/quote/types.rs | 37 ++++- rust/crates/candlesticks/src/market.rs | 130 ++++++++++-------- rust/crates/candlesticks/src/types.rs | 18 +++ rust/crates/candlesticks/tests/sh_time.rs | 126 +++++++++++++++++ rust/crates/proto/openapi-protobufs | 2 +- rust/crates/proto/src/longportapp.quote.v1.rs | 27 ++++ rust/src/quote/store.rs | 9 ++ 14 files changed, 474 insertions(+), 90 deletions(-) diff --git a/c/csrc/include/longport.h b/c/csrc/include/longport.h index d3edcebde..5b2b6b1ff 100644 --- a/c/csrc/include/longport.h +++ b/c/csrc/include/longport.h @@ -690,36 +690,72 @@ typedef enum lb_period_t { * One Minute */ PeriodMin1, + /** + * Two Minute + */ + PeriodMin2, + /** + * Three Minutes + */ + PeriodMin3, /** * Five Minutes */ PeriodMin5, + /** + * Ten Minutes + */ + PeriodMin10, /** * Fifteen Minutes */ PeriodMin15, + /** + * Twenty Minutes + */ + PeriodMin20, /** * Thirty Minutes */ PeriodMin30, /** - * Sixty Minutes + * Forty-Five Minutes + */ + PeriodMin45, + /** + * One Hour */ PeriodMin60, /** - * One Day + * Two Hours + */ + PeriodMin120, + /** + * Three Hours + */ + PeriodMin180, + /** + * Four Hours + */ + PeriodMin240, + /** + * Daily */ PeriodDay, /** - * One Week + * Weekly */ PeriodWeek, /** - * One Month + * Monthly */ PeriodMonth, /** - * One Year + * Quarterly + */ + PeriodQuarter, + /** + * Yearly */ PeriodYear, } lb_period_t; diff --git a/c/src/quote_context/enum_types.rs b/c/src/quote_context/enum_types.rs index cefb43606..73fac6c82 100644 --- a/c/src/quote_context/enum_types.rs +++ b/c/src/quote_context/enum_types.rs @@ -247,28 +247,55 @@ pub enum CPeriod { /// One Minute #[c(remote = "OneMinute")] PeriodMin1, + /// Two Minute + #[c(remote = "TwoMinute")] + PeriodMin2, + /// Three Minutes + #[c(remote = "ThreeMinute")] + PeriodMin3, /// Five Minutes #[c(remote = "FiveMinute")] PeriodMin5, + /// Ten Minutes + #[c(remote = "TenMinute")] + PeriodMin10, /// Fifteen Minutes #[c(remote = "FifteenMinute")] PeriodMin15, + /// Twenty Minutes + #[c(remote = "TwentyMinute")] + PeriodMin20, /// Thirty Minutes #[c(remote = "ThirtyMinute")] PeriodMin30, - /// Sixty Minutes + /// Forty-Five Minutes + #[c(remote = "FortyFiveMinute")] + PeriodMin45, + /// One Hour #[c(remote = "SixtyMinute")] PeriodMin60, - /// One Day + /// Two Hours + #[c(remote = "TwoHour")] + PeriodMin120, + /// Three Hours + #[c(remote = "ThreeHour")] + PeriodMin180, + /// Four Hours + #[c(remote = "FourHour")] + PeriodMin240, + /// Daily #[c(remote = "Day")] PeriodDay, - /// One Week + /// Weekly #[c(remote = "Week")] PeriodWeek, - /// One Month + /// Monthly #[c(remote = "Month")] PeriodMonth, - /// One Year + /// Quarterly + #[c(remote = "Quarter")] + PeriodQuarter, + /// Yearly #[c(remote = "Year")] PeriodYear, } diff --git a/cpp/include/types.hpp b/cpp/include/types.hpp index f8310efa8..dea817dc7 100644 --- a/cpp/include/types.hpp +++ b/cpp/include/types.hpp @@ -126,25 +126,43 @@ struct DerivativeType /// Candlestick period enum class Period { - /// Unknown, + /// Unknown Unknown, /// One Minute Min1, + /// Two Minute + Min2, + /// Three Minutes + Min3, /// Five Minutes Min5, + /// Ten Minutes + Min10, /// Fifteen Minutes Min15, + /// Twenty Minutes + Min20, /// Thirty Minutes Min30, - /// Sixty Minutes + /// Forty-Five Minutes + Min45, + /// One Hour Min60, - /// One Day + /// Two Hours + Min120, + /// Three Hours + Min180, + /// Four Hours + Min240, + /// Daily Day, - /// One Week + /// Weekly Week, - /// One Month + /// Monthly Month, - /// One Year + /// Quarterly + Quarter, + /// Yearly Year, }; diff --git a/cpp/src/convert.hpp b/cpp/src/convert.hpp index 2cb694c25..f4b3bda43 100644 --- a/cpp/src/convert.hpp +++ b/cpp/src/convert.hpp @@ -172,20 +172,38 @@ convert(Period period) return PeriodUnknown; case Period::Min1: return PeriodMin1; + case Period::Min2: + return PeriodMin2; + case Period::Min3: + return PeriodMin3; case Period::Min5: return PeriodMin5; + case Period::Min10: + return PeriodMin10; case Period::Min15: return PeriodMin15; + case Period::Min20: + return PeriodMin20; case Period::Min30: return PeriodMin30; + case Period::Min45: + return PeriodMin45; case Period::Min60: return PeriodMin60; + case Period::Min120: + return PeriodMin120; + case Period::Min180: + return PeriodMin180; + case Period::Min240: + return PeriodMin240; case Period::Day: return PeriodDay; case Period::Week: return PeriodWeek; case Period::Month: return PeriodMonth; + case Period::Quarter: + return PeriodQuarter; case Period::Year: return PeriodYear; default: @@ -201,20 +219,36 @@ convert(lb_period_t period) return Period::Unknown; case PeriodMin1: return Period::Min1; + case PeriodMin2: + return Period::Min2; + case PeriodMin3: + return Period::Min3; case PeriodMin5: return Period::Min5; case PeriodMin15: return Period::Min15; + case PeriodMin20: + return Period::Min20; case PeriodMin30: return Period::Min30; + case PeriodMin45: + return Period::Min45; case PeriodMin60: return Period::Min60; + case PeriodMin120: + return Period::Min120; + case PeriodMin180: + return Period::Min180; + case PeriodMin240: + return Period::Min240; case PeriodDay: return Period::Day; case PeriodWeek: return Period::Week; case PeriodMonth: return Period::Month; + case PeriodQuarter: + return Period::Quarter; case PeriodYear: return Period::Year; default: diff --git a/java/javasrc/src/main/java/com/longport/quote/Period.java b/java/javasrc/src/main/java/com/longport/quote/Period.java index f99eb2f60..f08fa7c17 100644 --- a/java/javasrc/src/main/java/com/longport/quote/Period.java +++ b/java/javasrc/src/main/java/com/longport/quote/Period.java @@ -3,12 +3,21 @@ public enum Period { Unknown, Min_1, + Min_2, + Min_3, Min_5, + Min_10, Min_15, + Min_20, Min_30, + Min_45, Min_60, + Min_120, + Min_180, + Min_240, Day, Week, Month, + Quarter, Year, } diff --git a/java/src/types/enum_types.rs b/java/src/types/enum_types.rs index 60eb05abd..28cf703b5 100644 --- a/java/src/types/enum_types.rs +++ b/java/src/types/enum_types.rs @@ -136,18 +136,36 @@ impl_java_enum!( Unknown, #[java(remote = "OneMinute")] Min_1, + #[java(remote = "TwoMinute")] + Min_2, + #[java(remote = "ThreeMinute")] + Min_3, #[java(remote = "FiveMinute")] Min_5, + #[java(remote = "TenMinute")] + Min_10, #[java(remote = "FifteenMinute")] Min_15, + #[java(remote = "TwentyMinute")] + Min_20, #[java(remote = "ThirtyMinute")] Min_30, + #[java(remote = "FortyFiveMinute")] + Min_45, #[java(remote = "SixtyMinute")] Min_60, + #[java(remote = "TwoHour")] + Min_120, + #[java(remote = "ThreeHour")] + Min_180, + #[java(remote = "FourHour")] + Min_240, Day, Week, Month, - Year + #[java(remote = "Quarter")] + Quarter, + Year, ] ); diff --git a/nodejs/src/quote/types.rs b/nodejs/src/quote/types.rs index 4ab0ee245..33fb23b2b 100644 --- a/nodejs/src/quote/types.rs +++ b/nodejs/src/quote/types.rs @@ -237,31 +237,58 @@ pub enum WarrantType { #[derive(Debug, JsEnum, Hash, Eq, PartialEq)] #[js(remote = "longport::quote::Period")] pub enum Period { - /// One Minute + /// Unknown #[js(remote = "UnknownPeriod")] Unknown, /// One Minute #[js(remote = "OneMinute")] Min_1, + /// Two Minute + #[js(remote = "TwoMinute")] + Min_2, + /// Three Minutes + #[js(remote = "ThreeMinute")] + Min_3, /// Five Minutes #[js(remote = "FiveMinute")] Min_5, + /// Ten Minutes + #[js(remote = "TenMinute")] + Min_10, /// Fifteen Minutes #[js(remote = "FifteenMinute")] Min_15, + /// Twenty Minutes + #[js(remote = "TwentyMinute")] + Min_20, /// Thirty Minutes #[js(remote = "ThirtyMinute")] Min_30, - /// Sixty Minutes + /// Forty-Five Minutes + #[js(remote = "FortyFiveMinute")] + Min_45, + /// One Hour #[js(remote = "SixtyMinute")] Min_60, - /// One Day + /// Two Hours + #[js(remote = "TwoHour")] + Min_120, + /// Three Hours + #[js(remote = "ThreeHour")] + Min_180, + /// Four Hours + #[js(remote = "FourHour")] + Min_240, + /// Daily Day, - /// One Week + /// Weekly Week, - /// One Month + /// Monthly Month, - /// One Year + /// Quarterly + #[js(remote = "Quarter")] + Quarter, + /// Yearly Year, } diff --git a/python/src/quote/types.rs b/python/src/quote/types.rs index afe60f331..a36248285 100644 --- a/python/src/quote/types.rs +++ b/python/src/quote/types.rs @@ -191,25 +191,52 @@ pub(crate) enum Period { /// One Minute #[py(remote = "OneMinute")] Min_1, + /// Two Minute + #[py(remote = "TwoMinute")] + Min_2, + /// Three Minutes + #[py(remote = "ThreeMinute")] + Min_3, /// Five Minutes #[py(remote = "FiveMinute")] Min_5, + /// Ten Minutes + #[py(remote = "TenMinute")] + Min_10, /// Fifteen Minutes #[py(remote = "FifteenMinute")] Min_15, + /// Twenty Minutes + #[py(remote = "TwentyMinute")] + Min_20, /// Thirty Minutes #[py(remote = "ThirtyMinute")] Min_30, - /// Sixty Minutes + /// Forty-Five Minutes + #[py(remote = "FortyFiveMinute")] + Min_45, + /// One Hour #[py(remote = "SixtyMinute")] Min_60, - /// One Day + /// Two Hours + #[py(remote = "TwoHour")] + Min_120, + /// Three Hours + #[py(remote = "ThreeHour")] + Min_180, + /// Four Hours + #[py(remote = "FourHour")] + Min_240, + /// Daily Day, - /// One Week + /// Weekly Week, - /// One Month + /// Monthly Month, - /// One Year + /// Quarterly + #[py(remote = "Quarter")] + Quarter, + /// Yearly Year, } diff --git a/rust/crates/candlesticks/src/market.rs b/rust/crates/candlesticks/src/market.rs index 2c246a58f..4c8ef2e6d 100644 --- a/rust/crates/candlesticks/src/market.rs +++ b/rust/crates/candlesticks/src/market.rs @@ -1,7 +1,7 @@ use std::collections::HashSet; use rust_decimal::{prelude::FromPrimitive, Decimal}; -use time::{macros::time, Date, Duration, Month, OffsetDateTime, Time, Weekday}; +use time::{macros::time, Date, Duration, OffsetDateTime, Time, Weekday}; use time_tz::{OffsetDateTimeExt, PrimitiveDateTimeExt, Tz}; use crate::{ @@ -74,6 +74,8 @@ impl Market { where H: Days, { + use Period::*; + let t = t.to_timezone(self.timezone); let time = t.time(); let trade_sessions = if !half_days.contains(t.date()) { @@ -95,22 +97,18 @@ impl Market { }?; Some(match period { - Period::Min_1 => t.replace_time(Time::from_hms(time.hour(), time.minute(), 0).ok()?), - Period::Min_5 | Period::Min_15 | Period::Min_30 => { - let n = period.minutes() as i64; - let minutes = time.hour() as i64 * 60 + time.minute() as i64; - let minutes = (minutes / n) * n; - t.replace_time(Time::from_hms((minutes / 60) as u8, (minutes % 60) as u8, 0).ok()?) - } - Period::Min_60 => { + Min_1 => t.replace_time(Time::from_hms(time.hour(), time.minute(), 0).ok()?), + Min_2 | Min_3 | Min_5 | Min_10 | Min_15 | Min_20 | Min_30 | Min_45 | Min_60 + | Min_120 | Min_180 | Min_240 => { + let minutes = period.minutes() as i64; let (start, _, _) = &trade_sessions[n]; let start_minutes = start.hour() as i64 * 60 + start.minute() as i64; let current_minutes = time.hour() as i64 * 60 + time.minute() as i64; - let offset_minutes = ((current_minutes - start_minutes) / 60) * 60; + let offset_minutes = ((current_minutes - start_minutes) / minutes) * minutes; t.replace_time(*start + Duration::minutes(offset_minutes)) } - Period::Day => t.replace_time(time!(00:00:00)), - Period::Week => { + Day => t.replace_time(time!(00:00:00)), + Week => { let week = t.iso_week(); Date::from_iso_week_date(t.year(), week, Weekday::Monday) .ok()? @@ -119,9 +117,18 @@ impl Market { .assume_timezone(self.timezone) .take_first()? } - Period::Month => t.replace_day(1).ok()?.replace_time(time!(00:00:00)), - Period::Year => t - .replace_month(Month::January) + Month => t.replace_day(1).ok()?.replace_time(time!(00:00:00)), + Quarter => { + let month = t.month(); + let quarter = (month as u8 - 1) / 3; + t.replace_month(time::Month::try_from(quarter * 3 + 1).ok()?) + .ok()? + .replace_day(1) + .ok()? + .replace_time(time!(00:00:00)) + } + Year => t + .replace_month(time::Month::January) .ok()? .replace_day(1) .ok()? @@ -288,6 +295,8 @@ impl Market { H: Days, N: Days, { + use Period::*; + let current_time = current_time.to_timezone(self.timezone) - TICK_TIMEOUT; if !normal_days.contains(current_time.date()) && !half_days.contains(current_time.date()) { return UpdateAction::None; @@ -300,57 +309,56 @@ impl Market { let res = trade_sessions.find_session(current_time.time()); match period { - Period::Min_1 | Period::Min_5 | Period::Min_15 | Period::Min_30 | Period::Min_60 => { - match (res, input) { - ( - FindSessionResult::Between(_), - InputCandlestick::Normal(candlestick) - | InputCandlestick::Confirmed(candlestick), - ) => { - let current_candlestick_time = self - .candlestick_time(half_days, period, current_time) - .unwrap(); - if current_candlestick_time > candlestick.time { - make_append_new(current_candlestick_time, input) - } else { - UpdateAction::None - } + Min_1 | Min_2 | Min_3 | Min_5 | Min_10 | Min_15 | Min_20 | Min_30 | Min_45 | Min_60 + | Min_120 | Min_180 | Min_240 => match (res, input) { + ( + FindSessionResult::Between(_), + InputCandlestick::Normal(candlestick) + | InputCandlestick::Confirmed(candlestick), + ) => { + let current_candlestick_time = self + .candlestick_time(half_days, period, current_time) + .unwrap(); + if current_candlestick_time > candlestick.time { + make_append_new(current_candlestick_time, input) + } else { + UpdateAction::None } - (FindSessionResult::After(_), InputCandlestick::Normal(candlestick)) => { - let Some(current_candlestick_time) = - self.candlestick_time(half_days, period, current_time) - else { - return UpdateAction::Confirm(candlestick); - }; - if current_candlestick_time > candlestick.time { - make_append_new(current_candlestick_time, input) - } else { - UpdateAction::None - } + } + (FindSessionResult::After(_), InputCandlestick::Normal(candlestick)) => { + let Some(current_candlestick_time) = + self.candlestick_time(half_days, period, current_time) + else { + return UpdateAction::Confirm(candlestick); + }; + if current_candlestick_time > candlestick.time { + make_append_new(current_candlestick_time, input) + } else { + UpdateAction::None } - ( - _, - InputCandlestick::Normal(candlestick) - | InputCandlestick::Confirmed(candlestick), - ) => { - if current_time.date() > candlestick.time.date() { - make_append_new( - self.candlestick_time( - half_days, - period, - current_time.replace_time(trade_sessions[0].0), - ) - .unwrap(), - input, + } + ( + _, + InputCandlestick::Normal(candlestick) + | InputCandlestick::Confirmed(candlestick), + ) => { + if current_time.date() > candlestick.time.date() { + make_append_new( + self.candlestick_time( + half_days, + period, + current_time.replace_time(trade_sessions[0].0), ) - } else { - UpdateAction::None - } + .unwrap(), + input, + ) + } else { + UpdateAction::None } - _ => UpdateAction::None, } - } - Period::Day | Period::Week | Period::Month | Period::Year => match (res, input) { + _ => UpdateAction::None, + }, + Day | Week | Month | Quarter | Year => match (res, input) { (FindSessionResult::After(n), InputCandlestick::Normal(candlestick)) if n == trade_sessions.len() - 1 => { diff --git a/rust/crates/candlesticks/src/types.rs b/rust/crates/candlesticks/src/types.rs index 1e942fe3b..6bd9daef3 100644 --- a/rust/crates/candlesticks/src/types.rs +++ b/rust/crates/candlesticks/src/types.rs @@ -7,13 +7,22 @@ use crate::UpdateFields; #[allow(non_camel_case_types)] pub enum Period { Min_1, + Min_2, + Min_3, Min_5, + Min_10, Min_15, + Min_20, Min_30, + Min_45, Min_60, + Min_120, + Min_180, + Min_240, Day, Week, Month, + Quarter, Year, } @@ -21,10 +30,19 @@ impl Period { #[inline] pub(crate) fn minutes(&self) -> u8 { match self { + Period::Min_1 => 1, + Period::Min_2 => 2, + Period::Min_3 => 3, Period::Min_5 => 5, + Period::Min_10 => 10, Period::Min_15 => 15, + Period::Min_20 => 20, Period::Min_30 => 30, + Period::Min_45 => 45, Period::Min_60 => 60, + Period::Min_120 => 120, + Period::Min_180 => 180, + Period::Min_240 => 240, _ => unreachable!(), } } diff --git a/rust/crates/candlesticks/tests/sh_time.rs b/rust/crates/candlesticks/tests/sh_time.rs index 083ef655a..cb75eae85 100644 --- a/rust/crates/candlesticks/tests/sh_time.rs +++ b/rust/crates/candlesticks/tests/sh_time.rs @@ -22,6 +22,56 @@ fn sh_min1() { t.check_time(time!(15:10:00), None); } +#[test] +fn sh_min2() { + let t = TestCandlestickTime::new(&CN, Period::Min_2); + t.check_time(time!(09:20:00), None); + t.check_time(time!(09:29:59), None); + t.check_time(time!(09:30:00), time!(09:30:00)); + t.check_time(time!(09:30:01), time!(09:30:00)); + t.check_time(time!(09:31:00), time!(09:30:00)); + t.check_time(time!(09:31:01), time!(09:30:00)); + t.check_time(time!(09:32:00), time!(09:32:00)); + t.check_time(time!(09:32:01), time!(09:32:00)); + t.check_time(time!(11:29:59), time!(11:28:00)); + t.check_time(time!(11:30:00), None); + t.check_time(time!(11:31:00), None); + t.check_time(time!(13:00:00), time!(13:00:00)); + t.check_time(time!(13:00:01), time!(13:00:00)); + t.check_time(time!(13:01:00), time!(13:00:00)); + t.check_time(time!(14:59:59), time!(14:58:00)); + t.check_time(time!(15:00:00), time!(15:00:00)); + t.check_time(time!(15:01:00), time!(15:00:00)); + t.check_time(time!(15:09:59), time!(15:00:00)); + t.check_time(time!(15:10:00), None); +} + +#[test] +fn sh_min3() { + let t = TestCandlestickTime::new(&CN, Period::Min_3); + t.check_time(time!(09:20:00), None); + t.check_time(time!(09:29:59), None); + t.check_time(time!(09:30:00), time!(09:30:00)); + t.check_time(time!(09:30:01), time!(09:30:00)); + t.check_time(time!(09:31:00), time!(09:30:00)); + t.check_time(time!(09:31:01), time!(09:30:00)); + t.check_time(time!(09:32:00), time!(09:30:00)); + t.check_time(time!(09:32:01), time!(09:30:00)); + t.check_time(time!(09:33:00), time!(09:33:00)); + t.check_time(time!(09:33:01), time!(09:33:00)); + t.check_time(time!(11:29:59), time!(11:27:00)); + t.check_time(time!(11:30:00), None); + t.check_time(time!(11:31:00), None); + t.check_time(time!(13:00:00), time!(13:00:00)); + t.check_time(time!(13:00:01), time!(13:00:00)); + t.check_time(time!(13:01:00), time!(13:00:00)); + t.check_time(time!(14:59:59), time!(14:57:00)); + t.check_time(time!(15:00:00), time!(15:00:00)); + t.check_time(time!(15:01:00), time!(15:00:00)); + t.check_time(time!(15:09:59), time!(15:00:00)); + t.check_time(time!(15:10:00), None); +} + #[test] fn sh_min5() { let t = TestCandlestickTime::new(&CN, Period::Min_5); @@ -43,6 +93,46 @@ fn sh_min5() { t.check_time(time!(15:01:00), time!(15:00:00)); } +#[test] +fn sh_min10() { + let t = TestCandlestickTime::new(&CN, Period::Min_10); + t.check_time(time!(09:29:59), None); + t.check_time(time!(09:30:00), time!(09:30:00)); + t.check_time(time!(09:39:59), time!(09:30:00)); + t.check_time(time!(09:40:00), time!(09:40:00)); + t.check_time(time!(09:40:01), time!(09:40:00)); + t.check_time(time!(10:29:59), time!(10:20:00)); + t.check_time(time!(10:30:00), time!(10:30:00)); + t.check_time(time!(10:31:00), time!(10:30:00)); + t.check_time(time!(10:37:00), time!(10:30:00)); + t.check_time(time!(13:00:00), time!(13:00:00)); + t.check_time(time!(13:00:05), time!(13:00:00)); + t.check_time(time!(13:09:59), time!(13:00:00)); + t.check_time(time!(14:59:59), time!(14:50:00)); + t.check_time(time!(15:00:00), time!(15:00:00)); + t.check_time(time!(15:01:00), time!(15:00:00)); +} + +#[test] +fn sh_min45() { + let t = TestCandlestickTime::new(&CN, Period::Min_45); + t.check_time(time!(09:29:59), None); + t.check_time(time!(09:30:00), time!(09:30:00)); + t.check_time(time!(09:59:59), time!(09:30:00)); + t.check_time(time!(10:00:00), time!(09:30:00)); + t.check_time(time!(10:00:01), time!(09:30:00)); + t.check_time(time!(10:15:0), time!(10:15:00)); + t.check_time(time!(10:30:00), time!(10:15:00)); + t.check_time(time!(10:31:00), time!(10:15:00)); + t.check_time(time!(10:37:00), time!(10:15:00)); + t.check_time(time!(13:00:00), time!(13:00:00)); + t.check_time(time!(13:00:05), time!(13:00:00)); + t.check_time(time!(13:09:59), time!(13:00:00)); + t.check_time(time!(14:59:59), time!(14:30:00)); + t.check_time(time!(15:00:00), time!(14:30:00)); + t.check_time(time!(15:01:00), time!(14:30:00)); +} + #[test] fn sh_min60() { let t = TestCandlestickTime::new(&CN, Period::Min_60); @@ -60,6 +150,24 @@ fn sh_min60() { t.check_time(time!(15:10:00), None); } +#[test] +fn sh_min240() { + let t = TestCandlestickTime::new(&CN, Period::Min_240); + t.check_time(time!(09:10:00), None); + t.check_time(time!(09:29:59), None); + t.check_time(time!(09:30:00), time!(09:30:00)); + t.check_time(time!(10:49:00), time!(09:30:00)); + t.check_time(time!(10:49:00), time!(09:30:00)); + t.check_time(time!(11:26:00), time!(09:30:00)); + t.check_time(time!(13:00:00), time!(13:00:00)); + t.check_time(time!(13:59:59), time!(13:00:00)); + t.check_time(time!(14:00:00), time!(13:00:00)); + t.check_time(time!(14:59:59), time!(13:00:00)); + t.check_time(time!(15:00:00), time!(13:00:00)); + t.check_time(time!(15:05:00), time!(13:00:00)); + t.check_time(time!(15:10:00), None); +} + #[test] fn sh_day() { let t = TestCandlestickTime::new(&CN, Period::Day); @@ -98,6 +206,24 @@ fn sh_month() { t.check_datetime(datetime!(2022-5-10 9:30:0 +8), datetime!(2022-5-1 0:0:0 +8)); } +#[test] +fn sh_quarter() { + let t = TestCandlestickTime::new(&CN, Period::Quarter); + t.check_datetime(datetime!(2022-1-6 9:30:0 +8), datetime!(2022-1-1 0:0:0 +8)); + t.check_datetime(datetime!(2022-4-6 9:30:0 +8), datetime!(2022-4-1 0:0:0 +8)); + t.check_datetime(datetime!(2022-6-6 9:30:0 +8), datetime!(2022-4-1 0:0:0 +8)); + t.check_datetime(datetime!(2022-7-6 9:30:0 +8), datetime!(2022-7-1 0:0:0 +8)); + t.check_datetime(datetime!(2022-9-6 9:30:0 +8), datetime!(2022-7-1 0:0:0 +8)); + t.check_datetime( + datetime!(2022-10-6 9:30:0 +8), + datetime!(2022-10-1 0:0:0 +8), + ); + t.check_datetime( + datetime!(2022-12-6 9:30:0 +8), + datetime!(2022-10-1 0:0:0 +8), + ); +} + #[test] fn sh_year() { let t = TestCandlestickTime::new(&CN, Period::Year); diff --git a/rust/crates/proto/openapi-protobufs b/rust/crates/proto/openapi-protobufs index 28b1a2c12..fa81c593f 160000 --- a/rust/crates/proto/openapi-protobufs +++ b/rust/crates/proto/openapi-protobufs @@ -1 +1 @@ -Subproject commit 28b1a2c125bf67c5935000fa324c41d7030f3b1a +Subproject commit fa81c593f48f31ba8933d04d747959aa38b4ed74 diff --git a/rust/crates/proto/src/longportapp.quote.v1.rs b/rust/crates/proto/src/longportapp.quote.v1.rs index f164e0f30..50e462f26 100644 --- a/rust/crates/proto/src/longportapp.quote.v1.rs +++ b/rust/crates/proto/src/longportapp.quote.v1.rs @@ -1228,13 +1228,22 @@ impl AdjustType { pub enum Period { UnknownPeriod = 0, OneMinute = 1, + TwoMinute = 2, + ThreeMinute = 3, FiveMinute = 5, + TenMinute = 10, FifteenMinute = 15, + TwentyMinute = 20, ThirtyMinute = 30, + FortyFiveMinute = 45, SixtyMinute = 60, + TwoHour = 120, + ThreeHour = 180, + FourHour = 240, Day = 1000, Week = 2000, Month = 3000, + Quarter = 3500, Year = 4000, } impl Period { @@ -1246,13 +1255,22 @@ impl Period { match self { Self::UnknownPeriod => "UNKNOWN_PERIOD", Self::OneMinute => "ONE_MINUTE", + Self::TwoMinute => "TWO_MINUTE", + Self::ThreeMinute => "THREE_MINUTE", Self::FiveMinute => "FIVE_MINUTE", + Self::TenMinute => "TEN_MINUTE", Self::FifteenMinute => "FIFTEEN_MINUTE", + Self::TwentyMinute => "TWENTY_MINUTE", Self::ThirtyMinute => "THIRTY_MINUTE", + Self::FortyFiveMinute => "FORTY_FIVE_MINUTE", Self::SixtyMinute => "SIXTY_MINUTE", + Self::TwoHour => "TWO_HOUR", + Self::ThreeHour => "THREE_HOUR", + Self::FourHour => "FOUR_HOUR", Self::Day => "DAY", Self::Week => "WEEK", Self::Month => "MONTH", + Self::Quarter => "QUARTER", Self::Year => "YEAR", } } @@ -1261,13 +1279,22 @@ impl Period { match value { "UNKNOWN_PERIOD" => Some(Self::UnknownPeriod), "ONE_MINUTE" => Some(Self::OneMinute), + "TWO_MINUTE" => Some(Self::TwoMinute), + "THREE_MINUTE" => Some(Self::ThreeMinute), "FIVE_MINUTE" => Some(Self::FiveMinute), + "TEN_MINUTE" => Some(Self::TenMinute), "FIFTEEN_MINUTE" => Some(Self::FifteenMinute), + "TWENTY_MINUTE" => Some(Self::TwentyMinute), "THIRTY_MINUTE" => Some(Self::ThirtyMinute), + "FORTY_FIVE_MINUTE" => Some(Self::FortyFiveMinute), "SIXTY_MINUTE" => Some(Self::SixtyMinute), + "TWO_HOUR" => Some(Self::TwoHour), + "THREE_HOUR" => Some(Self::ThreeHour), + "FOUR_HOUR" => Some(Self::FourHour), "DAY" => Some(Self::Day), "WEEK" => Some(Self::Week), "MONTH" => Some(Self::Month), + "QUARTER" => Some(Self::Quarter), "YEAR" => Some(Self::Year), _ => None, } diff --git a/rust/src/quote/store.rs b/rust/src/quote/store.rs index 56c795a2d..2c0932263 100644 --- a/rust/src/quote/store.rs +++ b/rust/src/quote/store.rs @@ -278,13 +278,22 @@ fn convert_period(period: Period) -> longport_candlesticks::Period { match period { Period::UnknownPeriod => unreachable!(), Period::OneMinute => Min_1, + Period::TwoMinute => Min_2, + Period::ThreeMinute => Min_3, Period::FiveMinute => Min_5, + Period::TenMinute => Min_10, Period::FifteenMinute => Min_15, + Period::TwentyMinute => Min_20, Period::ThirtyMinute => Min_30, + Period::FortyFiveMinute => Min_45, Period::SixtyMinute => Min_60, + Period::TwoHour => Min_120, + Period::ThreeHour => Min_180, + Period::FourHour => Min_240, Period::Day => Day, Period::Week => Week, Period::Month => Month, + Period::Quarter => Quarter, Period::Year => Year, } }