Skip to main content

longbridge/dca/
types.rs

1#![allow(missing_docs)]
2
3use rust_decimal::Decimal;
4use serde::{Deserialize, Serialize};
5
6use crate::{types::Market, utils::counter::deserialize_counter_id_as_symbol};
7
8/// Response for [`crate::DCAContext::list`] and write operations
9#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct DcaList {
11    /// DCA plans
12    pub plans: Vec<DcaPlan>,
13}
14
15/// One DCA (dollar-cost averaging) investment plan
16#[derive(Debug, Clone, Serialize, Deserialize)]
17pub struct DcaPlan {
18    /// Plan ID
19    pub plan_id: String,
20    /// Status
21    #[serde(default)]
22    pub status: DCAStatus,
23    /// Security symbol
24    #[serde(
25        rename = "counter_id",
26        deserialize_with = "deserialize_counter_id_as_symbol"
27    )]
28    pub symbol: String,
29    /// Member ID
30    #[serde(default)]
31    pub member_id: String,
32    /// Account ID
33    #[serde(default)]
34    pub aaid: String,
35    /// Account channel
36    #[serde(default)]
37    pub account_channel: String,
38    /// Display account
39    #[serde(default)]
40    pub display_account: String,
41    /// Market
42    #[serde(default)]
43    pub market: Market,
44    /// Investment amount per period
45    #[serde(default, with = "crate::serde_utils::decimal_empty_is_0")]
46    pub per_invest_amount: Decimal,
47    /// Investment frequency
48    #[serde(default)]
49    pub invest_frequency: DCAFrequency,
50    /// Day of week for weekly plans (e.g. `"Mon"`)
51    #[serde(default)]
52    pub invest_day_of_week: String,
53    /// Day of month for monthly plans
54    #[serde(default)]
55    pub invest_day_of_month: String,
56    /// Whether margin finance is allowed
57    #[serde(default)]
58    pub allow_margin_finance: bool,
59    /// Reminder notification hours before execution (API may return integer or
60    /// string)
61    #[serde(
62        default,
63        deserialize_with = "crate::serde_utils::deserialize_string_or_int_as_string"
64    )]
65    pub alter_hours: String,
66    /// Creation time
67    #[serde(default)]
68    pub created_at: String,
69    /// Last updated time
70    #[serde(default)]
71    pub updated_at: String,
72    /// Next investment date
73    #[serde(default)]
74    pub next_trd_date: String,
75    /// Security name
76    #[serde(default)]
77    pub stock_name: String,
78    /// Cumulative invested amount
79    #[serde(default, with = "crate::serde_utils::decimal_opt_str_is_none")]
80    pub cum_amount: Option<Decimal>,
81    /// Number of completed investment periods
82    #[serde(default)]
83    pub issue_number: i64,
84    /// Average cost
85    #[serde(default, with = "crate::serde_utils::decimal_opt_str_is_none")]
86    pub average_cost: Option<Decimal>,
87    /// Cumulative profit/loss
88    #[serde(default, with = "crate::serde_utils::decimal_opt_str_is_none")]
89    pub cum_profit: Option<Decimal>,
90}
91
92/// Response for [`crate::DCAContext::stats`]
93#[derive(Debug, Clone, Default, Serialize, Deserialize)]
94pub struct DcaStats {
95    /// Number of active plans
96    #[serde(default)]
97    pub active_count: String,
98    /// Number of finished plans
99    #[serde(default)]
100    pub finished_count: String,
101    /// Number of suspended plans
102    #[serde(default)]
103    pub suspended_count: String,
104    /// Nearest upcoming plans
105    #[serde(default)]
106    pub nearest_plans: Vec<DcaPlan>,
107    /// Days until next investment
108    #[serde(default)]
109    pub rest_days: String,
110    /// Total invested amount
111    #[serde(default, with = "crate::serde_utils::decimal_opt_str_is_none")]
112    pub total_amount: Option<Decimal>,
113    /// Total profit/loss
114    #[serde(default, with = "crate::serde_utils::decimal_opt_str_is_none")]
115    pub total_profit: Option<Decimal>,
116}
117
118/// Response for [`crate::DCAContext::check_support`]
119#[derive(Debug, Clone, Serialize, Deserialize)]
120pub struct DcaSupportList {
121    /// Support info per security
122    pub infos: Vec<DcaSupportInfo>,
123}
124
125/// DCA support info for one security
126#[derive(Debug, Clone, Serialize, Deserialize)]
127pub struct DcaSupportInfo {
128    /// Security symbol
129    #[serde(
130        rename = "counter_id",
131        deserialize_with = "deserialize_counter_id_as_symbol"
132    )]
133    pub symbol: String,
134    /// Whether DCA is supported for this security
135    pub support_regular_saving: bool,
136}
137
138/// Response for [`crate::DCAContext::history`]
139#[derive(Debug, Clone, Serialize, Deserialize)]
140pub struct DcaHistoryResponse {
141    /// Execution history records
142    pub records: Vec<DcaHistoryRecord>,
143    /// Whether more records exist
144    #[serde(default)]
145    pub has_more: bool,
146}
147
148/// One DCA execution record
149#[derive(Debug, Clone, Serialize, Deserialize)]
150pub struct DcaHistoryRecord {
151    /// Execution time
152    pub created_at: String,
153    /// Associated order ID
154    pub order_id: String,
155    /// Status
156    pub status: String,
157    /// Action type
158    pub action: String,
159    /// Order type
160    pub order_type: String,
161    /// Executed quantity
162    #[serde(default, with = "crate::serde_utils::decimal_opt_str_is_none")]
163    pub executed_qty: Option<Decimal>,
164    /// Executed price
165    #[serde(default, with = "crate::serde_utils::decimal_opt_str_is_none")]
166    pub executed_price: Option<Decimal>,
167    /// Executed amount
168    #[serde(default, with = "crate::serde_utils::decimal_opt_str_is_none")]
169    pub executed_amount: Option<Decimal>,
170    /// Rejection reason (if any)
171    pub rejected_reason: String,
172    /// Security symbol
173    #[serde(
174        rename = "counter_id",
175        deserialize_with = "deserialize_counter_id_as_symbol"
176    )]
177    pub symbol: String,
178}
179
180/// DCA investment frequency
181#[derive(Debug, Copy, Clone, Eq, PartialEq, Serialize, Deserialize, Default)]
182pub enum DCAFrequency {
183    /// Daily investment
184    #[serde(rename = "Daily")]
185    Daily,
186    /// Weekly investment
187    #[serde(rename = "Weekly")]
188    Weekly,
189    /// Fortnightly (every two weeks) investment
190    #[serde(rename = "Fortnightly")]
191    Fortnightly,
192    /// Monthly investment
193    #[default]
194    #[serde(rename = "Monthly")]
195    Monthly,
196}
197
198/// Response for [`crate::DCAContext::create`] and [`crate::DCAContext::update`]
199#[derive(Debug, Clone, Serialize, Deserialize)]
200pub struct DcaCreateResult {
201    /// The plan ID of the created or updated plan
202    pub plan_id: String,
203}
204
205/// Response for [`crate::DCAContext::calc_date`]
206#[derive(Debug, Clone, Serialize, Deserialize)]
207pub struct DcaCalcDateResult {
208    /// Next projected trade date (unix timestamp string)
209    pub trade_date: String,
210}
211
212/// DCA plan status
213#[derive(Debug, Copy, Clone, Eq, PartialEq, Serialize, Deserialize, Default)]
214pub enum DCAStatus {
215    /// Active plan
216    #[default]
217    #[serde(rename = "Active")]
218    Active,
219    /// Suspended plan
220    #[serde(rename = "Suspended")]
221    Suspended,
222    /// Finished plan
223    #[serde(rename = "Finished")]
224    Finished,
225}