1use rust_decimal::Decimal;
2use serde::{Deserialize, Serialize};
3use serde_repr::{Deserialize_repr, Serialize_repr};
4use strum_macros::{FromRepr, IntoStaticStr};
5use time::OffsetDateTime;
6
7use crate::types::Market;
8
9#[allow(non_camel_case_types)]
13#[derive(
14 Debug,
15 Clone,
16 Copy,
17 Default,
18 Hash,
19 PartialOrd,
20 Ord,
21 PartialEq,
22 Eq,
23 FromRepr,
24 IntoStaticStr,
25 Serialize_repr,
26 Deserialize_repr,
27)]
28#[repr(i32)]
29pub enum TradeStatus {
30 #[default]
32 #[serde(other)]
33 UNKNOWN = -1,
34 NO_REGISTER_QUOTE = 0,
36 CLEAN = 101,
38 OPEN_BID = 102,
40 MORNING_CLOSING = 103,
42 TRADING = 105,
44 NOON_CLOSING = 106,
46 CLOSE_BID = 107,
48 CLOSING = 108,
50 DARK_WAIT = 110,
52 DARK_TRADING = 111,
54 DARK_CLOSING = 112,
56 AFTER_FIX = 120,
58 HALF_CLOSING = 121,
61 NOT_OPENED = 122,
64 REALTIME_QUOTE = 123,
67 US_PREV = 201,
69 US_TRADING = 202,
71 US_AFTER = 203,
73 US_CLOSING = 204,
75 US_STOP = 205,
77 US_CLEAN = 206,
79 US_NIGHT = 207,
81 US_PREV_MARKET_CLEAN = 209,
83 US_AFTER_MARKET_CLEAN = 210,
85 REFRESH = 1000,
87 DELIST = 1001,
89 PREPARE = 1002,
91 CODE_CHANGE = 1003,
93 STOP = 1004,
95 WILL_OPEN = 1005,
97 COMMON_SUSPEND = 1006,
99 EXPIRE = 1007,
101 NO_QUOTE = 1008,
103 UNITED = 1009,
105 TRADING_HALT = 1010,
107 WAIT_LISTING = 1011,
109 FUSE = 2001,
111}
112
113impl From<i32> for TradeStatus {
114 fn from(value: i32) -> Self {
115 Self::from_repr(value).unwrap_or_default()
116 }
117}
118
119impl TradeStatus {
120 pub fn from_isize(value: isize) -> TradeStatus {
122 (value as i32).into()
123 }
124
125 pub fn code(self) -> i32 {
127 self as i32
128 }
129
130 pub fn as_static(self) -> &'static str {
132 self.into()
133 }
134
135 pub fn label(self) -> &'static str {
137 let status = self.normalize();
138 match status {
139 TradeStatus::US_PREV
140 | TradeStatus::US_TRADING
141 | TradeStatus::US_AFTER
142 | TradeStatus::US_NIGHT
143 | TradeStatus::US_CLOSING
144 | TradeStatus::TRADING
145 | TradeStatus::CLOSING => status.name(),
146 _ => "",
147 }
148 }
149
150 pub fn name(self) -> &'static str {
152 match self.normalize() {
153 TradeStatus::UNKNOWN | TradeStatus::NO_REGISTER_QUOTE => "Unknown",
154 TradeStatus::OPEN_BID => "Open Bid",
155 TradeStatus::MORNING_CLOSING => "Morning Break",
156 TradeStatus::TRADING | TradeStatus::US_TRADING | TradeStatus::US_AFTER_MARKET_CLEAN => {
157 "Trading"
158 }
159 TradeStatus::NOON_CLOSING => "Mid-Day Break",
160 TradeStatus::CLOSE_BID => "Close Bid",
161 TradeStatus::CLOSING
162 | TradeStatus::CLEAN
163 | TradeStatus::HALF_CLOSING
164 | TradeStatus::US_CLOSING
165 | TradeStatus::US_PREV_MARKET_CLEAN => "Closed",
166 TradeStatus::DARK_WAIT => "Dark Wait",
167 TradeStatus::DARK_TRADING => "Dark Trading",
168 TradeStatus::DARK_CLOSING => "Closing",
169 TradeStatus::AFTER_FIX => "After Fix",
170 TradeStatus::NOT_OPENED => "Not Open",
171 TradeStatus::REALTIME_QUOTE => "Temporary Break",
172 TradeStatus::US_PREV | TradeStatus::US_CLEAN => "Pre-Market",
173 TradeStatus::US_AFTER => "Post-Market",
174 TradeStatus::US_STOP | TradeStatus::STOP => "Stop",
175 TradeStatus::US_NIGHT => "Overnight",
176 TradeStatus::REFRESH => "Refresh",
177 TradeStatus::DELIST => "Delist",
178 TradeStatus::PREPARE => "Prepare",
179 TradeStatus::CODE_CHANGE => "Code Change",
180 TradeStatus::WILL_OPEN => "Will Open",
181 TradeStatus::COMMON_SUSPEND => "Common Suspend",
182 TradeStatus::EXPIRE => "Expire",
183 TradeStatus::NO_QUOTE => "No Quote",
184 TradeStatus::UNITED => "Not Listed",
185 TradeStatus::TRADING_HALT => "Terminated",
186 TradeStatus::WAIT_LISTING => "Wait Listing",
187 TradeStatus::FUSE => "Fuse",
188 }
189 }
190
191 pub fn is_us_market(self) -> bool {
193 self.code() >= 200 && self.code() < 300
194 }
195
196 pub fn is_us_pre_post(self) -> bool {
198 self.is_us_prev() || self.is_us_after()
199 }
200
201 pub fn is_us_night(self) -> bool {
203 matches!(self, TradeStatus::US_NIGHT)
204 }
205
206 pub fn is_us_closing(self) -> bool {
208 matches!(
209 self,
210 TradeStatus::US_CLOSING | TradeStatus::US_PREV_MARKET_CLEAN
211 )
212 }
213
214 pub fn is_closing(self) -> bool {
216 matches!(
217 self,
218 TradeStatus::US_CLOSING
219 | TradeStatus::US_PREV_MARKET_CLEAN
220 | TradeStatus::CLOSING
221 | TradeStatus::HALF_CLOSING
222 )
223 }
224
225 pub fn is_us_prev(self) -> bool {
227 matches!(self, TradeStatus::US_PREV | TradeStatus::US_CLEAN)
228 }
229
230 pub fn is_us_after(self) -> bool {
232 matches!(self, TradeStatus::US_AFTER)
233 }
234
235 pub fn is_trading(self) -> bool {
237 matches!(
238 self,
239 TradeStatus::TRADING | TradeStatus::US_TRADING | TradeStatus::US_AFTER_MARKET_CLEAN
240 )
241 }
242
243 pub fn is_dark(self) -> bool {
245 matches!(
246 self,
247 TradeStatus::DARK_WAIT | TradeStatus::DARK_TRADING | TradeStatus::DARK_CLOSING
248 )
249 }
250
251 pub fn allow_trading(self) -> bool {
253 matches!(
254 self,
255 TradeStatus::OPEN_BID
256 | TradeStatus::TRADING
257 | TradeStatus::CLOSE_BID
258 | TradeStatus::NOT_OPENED
259 | TradeStatus::NOON_CLOSING
260 | TradeStatus::US_TRADING
261 | TradeStatus::US_AFTER_MARKET_CLEAN
262 )
263 }
264
265 #[must_use]
267 pub fn normalize(self) -> Self {
268 match self {
269 TradeStatus::CLEAN => TradeStatus::CLOSING,
270 TradeStatus::US_PREV_MARKET_CLEAN => TradeStatus::US_CLOSING,
271 TradeStatus::US_CLEAN => TradeStatus::US_PREV,
272 TradeStatus::US_AFTER_MARKET_CLEAN => TradeStatus::US_TRADING,
273 _ => self,
274 }
275 }
276
277 pub fn is_special(self) -> bool {
279 self.code() < 100 || self == Self::US_STOP || self.code() >= 1000
280 }
281}
282
283#[derive(Debug, Clone, Serialize, Deserialize)]
285pub struct MarketStatusResponse {
286 pub market_time: Vec<MarketTimeItem>,
288}
289
290#[derive(Debug, Clone, Serialize, Deserialize)]
292pub struct MarketTimeItem {
293 pub market: Market,
295 pub trade_status: TradeStatus,
297 pub timestamp: String,
299 pub delay_trade_status: TradeStatus,
302 pub delay_timestamp: String,
304 pub sub_status: i32,
306 pub delay_sub_status: i32,
308}
309
310#[cfg(test)]
311mod tests {
312 use crate::market::TradeStatus;
313
314 #[test]
315 fn market_trade_status_deserializes_numeric_codes() {
316 assert_eq!(
317 serde_json::from_str::<TradeStatus>("202")
318 .expect("202 should deserialize as market trade status"),
319 TradeStatus::US_TRADING
320 );
321 assert_eq!(
322 serde_json::from_str::<TradeStatus>("456")
323 .expect("unknown numeric status should deserialize"),
324 TradeStatus::UNKNOWN
325 );
326 }
327
328 #[test]
329 fn market_trade_status_serializes_as_numeric_code() {
330 let value = serde_json::to_string(&TradeStatus::US_CLEAN)
331 .expect("market trade status should serialize");
332 assert_eq!(value, "206");
333 }
334
335 #[test]
336 fn market_trade_status_normalizes_engine_aliases() {
337 assert_eq!(TradeStatus::CLEAN.normalize(), TradeStatus::CLOSING);
338 assert_eq!(TradeStatus::US_CLEAN.normalize(), TradeStatus::US_PREV);
339 assert_eq!(
340 TradeStatus::US_PREV_MARKET_CLEAN.normalize(),
341 TradeStatus::US_CLOSING
342 );
343 assert_eq!(
344 TradeStatus::US_AFTER_MARKET_CLEAN.normalize(),
345 TradeStatus::US_TRADING
346 );
347 }
348
349 #[test]
350 fn market_trade_status_label_matches_engine_simplified_display() {
351 assert_eq!(TradeStatus::US_PREV.label(), "Pre-Market");
352 assert_eq!(TradeStatus::US_CLEAN.label(), "Pre-Market");
353 assert_eq!(TradeStatus::US_AFTER.label(), "Post-Market");
354 assert_eq!(TradeStatus::US_CLOSING.label(), "Closed");
355 assert_eq!(TradeStatus::US_AFTER_MARKET_CLEAN.label(), "Trading");
356 assert_eq!(TradeStatus::US_TRADING.label(), "Trading");
357 assert_eq!(TradeStatus::TRADING.label(), "Trading");
358 assert_eq!(TradeStatus::CLEAN.label(), "Closed");
359 assert_eq!(TradeStatus::OPEN_BID.label(), "");
360 assert_eq!(TradeStatus::NOON_CLOSING.label(), "");
361 }
362
363 #[test]
364 fn market_trade_status_name_covers_full_status_set() {
365 let cases = [
366 (TradeStatus::MORNING_CLOSING, "Morning Break"),
367 (TradeStatus::NOON_CLOSING, "Mid-Day Break"),
368 (TradeStatus::REALTIME_QUOTE, "Temporary Break"),
369 (TradeStatus::US_STOP, "Stop"),
370 (TradeStatus::TRADING_HALT, "Terminated"),
371 (TradeStatus::WAIT_LISTING, "Wait Listing"),
372 (TradeStatus::FUSE, "Fuse"),
373 (TradeStatus::UNKNOWN, "Unknown"),
374 (TradeStatus::NO_REGISTER_QUOTE, "Unknown"),
375 ];
376
377 for (status, expected) in cases {
378 assert_eq!(status.name(), expected, "status {status:?}");
379 }
380 }
381
382 #[test]
383 fn market_trade_status_codes_match_phase_definition_document() {
384 let codes = [
385 101, 102, 103, 105, 106, 107, 108, 110, 111, 112, 120, 121, 122, 123, 201, 202, 203,
386 204, 206, 207, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011,
387 2001,
388 ];
389
390 for code in codes {
391 assert_eq!(TradeStatus::from(code).code(), code, "status code {code}");
392 }
393 }
394
395 #[test]
396 fn market_trade_status_names_match_phase_definition_document() {
397 let cases = [
398 (123, "Temporary Break"),
399 (1009, "Not Listed"),
400 (1010, "Terminated"),
401 (2001, "Fuse"),
402 ];
403
404 for (code, expected) in cases {
405 assert_eq!(
406 TradeStatus::from(code).name(),
407 expected,
408 "status code {code}"
409 );
410 }
411 }
412
413 #[test]
414 fn market_time_item_uses_market_trade_status_type() {
415 let item = serde_json::from_str::<crate::market::MarketTimeItem>(
416 r#"{
417 "market": "US",
418 "trade_status": 202,
419 "timestamp": "1717200000",
420 "delay_trade_status": 204,
421 "delay_timestamp": "1717200000",
422 "sub_status": 0,
423 "delay_sub_status": 0
424 }"#,
425 )
426 .expect("market time item should deserialize");
427
428 assert_eq!(item.trade_status, TradeStatus::US_TRADING);
429 assert_eq!(item.delay_trade_status, TradeStatus::US_CLOSING);
430 }
431}
432
433#[derive(Debug, Clone, Serialize, Deserialize)]
437pub struct BrokerHoldingTop {
438 pub buy: Vec<BrokerHoldingEntry>,
440 pub sell: Vec<BrokerHoldingEntry>,
442 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
444 pub updated_at: String,
445}
446
447#[derive(Debug, Clone, Serialize, Deserialize)]
449pub struct BrokerHoldingEntry {
450 pub name: String,
452 pub parti_number: String,
454 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
456 pub chg: Option<Decimal>,
457 pub strong: bool,
459}
460
461#[derive(Debug, Clone, Serialize, Deserialize)]
465pub struct BrokerHoldingDetail {
466 pub list: Vec<BrokerHoldingDetailItem>,
468 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
470 pub updated_at: String,
471}
472
473#[derive(Debug, Clone, Serialize, Deserialize)]
475pub struct BrokerHoldingDetailItem {
476 pub name: String,
478 pub parti_number: String,
480 pub ratio: BrokerHoldingChanges,
482 pub shares: BrokerHoldingChanges,
484 pub strong: bool,
486}
487
488#[derive(Debug, Clone, Serialize, Deserialize)]
490pub struct BrokerHoldingChanges {
491 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
493 pub value: Option<Decimal>,
494 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
496 pub chg_1: Option<Decimal>,
497 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
499 pub chg_5: Option<Decimal>,
500 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
502 pub chg_20: Option<Decimal>,
503 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
505 pub chg_60: Option<Decimal>,
506}
507
508#[derive(Debug, Clone, Serialize, Deserialize)]
512pub struct BrokerHoldingDailyHistory {
513 pub list: Vec<BrokerHoldingDailyItem>,
515}
516
517#[derive(Debug, Clone, Serialize, Deserialize)]
519pub struct BrokerHoldingDailyItem {
520 pub date: String,
522 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
524 pub holding: Option<Decimal>,
525 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
527 pub ratio: Option<Decimal>,
528 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
530 pub chg: Option<Decimal>,
531}
532
533#[derive(Debug, Clone, Serialize, Deserialize)]
537pub struct AhPremiumKlines {
538 pub klines: Vec<AhPremiumKline>,
540}
541
542#[derive(Debug, Clone, Serialize, Deserialize)]
544pub struct AhPremiumIntraday {
545 pub klines: Vec<AhPremiumKline>,
547}
548
549#[derive(Debug, Clone, Serialize, Deserialize)]
551pub struct AhPremiumKline {
552 #[serde(with = "crate::serde_utils::decimal_empty_is_0")]
554 pub aprice: Decimal,
555 #[serde(with = "crate::serde_utils::decimal_empty_is_0")]
557 pub apreclose: Decimal,
558 #[serde(with = "crate::serde_utils::decimal_empty_is_0")]
560 pub hprice: Decimal,
561 #[serde(with = "crate::serde_utils::decimal_empty_is_0")]
563 pub hpreclose: Decimal,
564 #[serde(with = "crate::serde_utils::decimal_empty_is_0")]
566 pub currency_rate: Decimal,
567 #[serde(with = "crate::serde_utils::decimal_empty_is_0")]
569 pub ahpremium_rate: Decimal,
570 #[serde(with = "crate::serde_utils::decimal_empty_is_0")]
572 pub price_spread: Decimal,
573 #[serde(deserialize_with = "crate::serde_utils::deserialize_timestamp")]
575 pub timestamp: OffsetDateTime,
576}
577
578#[derive(Debug, Clone, Serialize, Deserialize)]
582pub struct TradeStatsResponse {
583 pub statistics: TradeStatistics,
585 pub trades: Vec<TradePriceLevel>,
587}
588
589#[derive(Debug, Clone, Serialize, Deserialize)]
591pub struct TradeStatistics {
592 #[serde(with = "crate::serde_utils::decimal_empty_is_0")]
594 pub avgprice: Decimal,
595 #[serde(with = "crate::serde_utils::decimal_empty_is_0")]
597 pub buy: Decimal,
598 #[serde(with = "crate::serde_utils::decimal_empty_is_0")]
600 pub neutral: Decimal,
601 #[serde(with = "crate::serde_utils::decimal_empty_is_0")]
603 pub preclose: Decimal,
604 #[serde(with = "crate::serde_utils::decimal_empty_is_0")]
606 pub sell: Decimal,
607 pub timestamp: String,
609 #[serde(with = "crate::serde_utils::decimal_empty_is_0")]
611 pub total_amount: Decimal,
612 pub trade_date: Vec<String>,
614 pub trades_count: String,
616}
617
618#[derive(Debug, Clone, Serialize, Deserialize)]
620pub struct TradePriceLevel {
621 #[serde(with = "crate::serde_utils::decimal_empty_is_0")]
623 pub buy_amount: Decimal,
624 #[serde(with = "crate::serde_utils::decimal_empty_is_0")]
626 pub neutral_amount: Decimal,
627 #[serde(with = "crate::serde_utils::decimal_empty_is_0")]
629 pub price: Decimal,
630 #[serde(with = "crate::serde_utils::decimal_empty_is_0")]
632 pub sell_amount: Decimal,
633}
634
635#[derive(Debug, Clone, Serialize, Deserialize)]
639pub struct AnomalyResponse {
640 pub all_off: bool,
642 pub changes: Vec<AnomalyItem>,
644}
645
646#[derive(Debug, Clone, Serialize, Deserialize)]
648pub struct AnomalyItem {
649 pub symbol: String,
651 pub name: String,
653 pub alert_name: String,
655 pub alert_time: i64,
657 pub change_values: Vec<String>,
659 pub emotion: i32,
661}
662
663#[derive(Debug, Clone, Serialize, Deserialize)]
667pub struct IndexConstituents {
668 pub fall_num: i32,
670 pub flat_num: i32,
672 pub rise_num: i32,
674 pub stocks: Vec<ConstituentStock>,
676}
677
678#[derive(Debug, Clone, Serialize, Deserialize)]
680pub struct ConstituentStock {
681 pub symbol: String,
683 pub name: String,
685 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
687 pub last_done: Option<Decimal>,
688 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
690 pub prev_close: Option<Decimal>,
691 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
693 pub inflow: Option<Decimal>,
694 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
696 pub balance: Option<Decimal>,
697 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
699 pub amount: Option<Decimal>,
700 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
702 pub total_shares: Option<Decimal>,
703 pub tags: Vec<String>,
705 pub intro: String,
707 pub market: String,
709 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
711 pub circulating_shares: Option<Decimal>,
712 pub delay: bool,
714 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
716 pub chg: Option<Decimal>,
717 pub trade_status: i32,
719}
720
721#[derive(Debug, Clone, Serialize, Deserialize)]
725pub struct TopMoversStock {
726 pub symbol: String,
728 pub code: String,
730 pub name: String,
732 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
734 pub full_name: String,
735 pub change: String,
737 pub last_done: String,
739 pub market: String,
741 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
743 pub labels: Vec<String>,
744 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
746 pub logo: String,
747}
748
749#[derive(Debug, Clone, Serialize, Deserialize)]
751pub struct TopMoversEvent {
752 pub timestamp: String,
754 pub alert_reason: String,
756 pub alert_type: i64,
758 pub stock: TopMoversStock,
760 pub post: serde_json::Value,
762}
763
764#[derive(Debug, Clone, Serialize, Deserialize)]
766pub struct TopMoversResponse {
767 pub events: Vec<TopMoversEvent>,
769 pub next_params: String,
772}
773
774#[derive(Debug, Clone, Serialize, Deserialize)]
779pub struct RankSubCategory {
780 pub key: String,
782 pub name: String,
784 pub market: String,
786}
787
788#[derive(Debug, Clone, Serialize, Deserialize)]
790pub struct RankCategory {
791 pub key: String,
793 pub name: String,
795 pub sub_categories: Vec<RankSubCategory>,
797}
798
799#[derive(Debug, Clone, Serialize, Deserialize)]
801pub struct RankCategoriesResponse {
802 pub categories: Vec<RankCategory>,
804}
805
806#[derive(Debug, Clone, Serialize, Deserialize)]
810pub struct RankListItem {
811 pub symbol: String,
813 pub code: String,
815 pub name: String,
817 pub last_done: String,
819 pub chg: String,
821 pub change: String,
823 pub inflow: String,
825 pub market_cap: String,
827 pub industry: String,
829 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
831 pub pre_post_price: String,
832 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
834 pub pre_post_chg: String,
835 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
837 pub amplitude: String,
838 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
840 pub five_day_chg: String,
841 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
843 pub turnover_rate: String,
844 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
846 pub volume_rate: String,
847 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
849 pub pb_ttm: String,
850}
851
852#[derive(Debug, Clone, Serialize, Deserialize)]
854pub struct RankListResponse {
855 pub bmp: bool,
857 pub lists: Vec<RankListItem>,
859}
860
861#[derive(Debug, Copy, Clone, Eq, PartialEq, Serialize, Deserialize, Default)]
865pub enum BrokerHoldingPeriod {
866 #[default]
868 #[serde(rename = "rct_1")]
869 Rct1,
870 #[serde(rename = "rct_5")]
872 Rct5,
873 #[serde(rename = "rct_20")]
875 Rct20,
876 #[serde(rename = "rct_60")]
878 Rct60,
879}
880
881#[derive(Debug, Copy, Clone, Eq, PartialEq, Default)]
883pub enum AhPremiumPeriod {
884 Min1,
886 Min5,
888 Min15,
890 Min30,
892 Min60,
894 #[default]
896 Day,
897 Week,
899 Month,
901 Year,
903}
904
905impl AhPremiumPeriod {
906 pub(crate) fn to_line_type(self) -> &'static str {
908 match self {
909 AhPremiumPeriod::Min1 => "1",
910 AhPremiumPeriod::Min5 => "5",
911 AhPremiumPeriod::Min15 => "15",
912 AhPremiumPeriod::Min30 => "30",
913 AhPremiumPeriod::Min60 => "60",
914 AhPremiumPeriod::Day => "1000",
915 AhPremiumPeriod::Week => "2000",
916 AhPremiumPeriod::Month => "3000",
917 AhPremiumPeriod::Year => "4000",
918 }
919 }
920}