use std::ops::{Deref, DerefMut};
use derive_setters::Setters;
use rust_decimal::Decimal;
use serde::{Deserialize, Serialize};
use crate::schema::enums::{ImpactLevel, MarginMode, ProfitMode, QuoteId, TimePeriod, TradeStatus, TradingAction, TradingCommand, TransactionStatus, TransactionType};
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize, Setters)]
#[setters(into, strip_option, prefix = "with_")]
#[serde(rename_all = "camelCase")]
pub struct LoginRequest {
pub user_id: String,
pub password: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub app_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub app_name: Option<String>,
}
#[derive(Default, Copy, Clone, PartialEq, Debug, Serialize, Deserialize)]
pub struct LoginResponse;
#[derive(Default, Copy, Clone, PartialEq, Debug, Serialize, Deserialize)]
pub struct GetAllSymbolsRequest;
#[derive(Clone, PartialEq, Debug, Default, Serialize, Deserialize)]
pub struct GetAllSymbolsResponse(pub Vec<SymbolRecord>);
impl Deref for GetAllSymbolsResponse {
type Target = Vec<SymbolRecord>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for GetAllSymbolsResponse {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize, Setters)]
#[setters(into, strip_option, prefix = "with_")]
#[serde(rename_all = "camelCase")]
pub struct SymbolRecord {
pub ask: Decimal,
pub bid: Decimal,
pub category_name: String,
pub contract_size: i64,
pub currency: String,
pub currency_pair: bool,
pub currency_profit: String,
pub description: String,
pub expiration: Option<u64>,
pub group_name: String,
pub high: Decimal,
pub initial_margin: i64,
pub instant_max_volume: i64,
pub leverage: Decimal,
pub long_only: bool,
pub lot_max: Decimal,
pub lot_min: Decimal,
pub lot_step: Decimal,
pub low: Decimal,
pub margin_hedged: i64,
pub margin_hedged_strong: bool,
pub margin_maintenance: Option<i64>,
pub margin_mode: MarginMode,
pub percentage: Decimal,
pub pips_precision: i64,
pub precision: i64,
pub profit_mode: ProfitMode,
pub quote_id: QuoteId,
pub short_selling: bool,
pub spread_raw: Decimal,
pub spread_table: Decimal,
pub starting: Option<u64>,
pub step_rule_id: i64,
pub stops_level: i64,
#[serde(rename = "swap_rollover3days")]
pub swap_rollover_3days: i64,
pub swap_enable: bool,
pub swap_long: Decimal,
pub swap_short: Decimal,
pub swap_type: i64,
pub symbol: String,
pub tick_size: Option<Decimal>,
pub tick_value: Option<Decimal>,
pub time: u64,
pub time_string: String,
pub trailing_enabled: bool,
pub type_: i64,
}
#[derive(Default, Copy, Clone, PartialEq, Debug, Serialize, Deserialize)]
pub struct GetCalendarRequest;
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize)]
pub struct GetCalendarResponse(pub Vec<CalendarRecord>);
impl Deref for GetCalendarResponse {
type Target = Vec<CalendarRecord>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for GetCalendarResponse {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize, Setters)]
#[setters(into, strip_option, prefix = "with_")]
#[serde(rename_all = "camelCase")]
pub struct CalendarRecord {
pub country: String,
pub current: String,
pub forecast: String,
pub impact: ImpactLevel,
pub period: String,
pub previous: String,
pub time: u64,
pub title: String,
}
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize, Setters)]
#[setters(into, strip_option, prefix = "with_")]
#[serde(rename_all = "camelCase")]
pub struct GetChartLastRequestRequest {
info: ChartLastInfoRecord
}
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize, Setters)]
#[setters(into, strip_option, prefix = "with_")]
#[serde(rename_all = "camelCase")]
pub struct ChartLastInfoRecord {
pub period: TimePeriod,
pub start: u64,
pub symbol: String,
}
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize, Setters)]
#[setters(into, strip_option, prefix = "with_")]
#[serde(rename_all = "camelCase")]
pub struct GetChartLastRequestResponse {
pub digits: i64,
pub rate_infos: Vec<RateInfoRecord>,
}
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize, Setters)]
#[setters(into, strip_option, prefix = "with_")]
#[serde(rename_all = "camelCase")]
pub struct RateInfoRecord {
pub close: Decimal,
pub ctm: u64,
pub ctm_string: String,
pub high: Decimal,
pub low: Decimal,
pub open: Decimal,
pub vol: Decimal,
}
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize, Setters)]
#[setters(into, strip_option, prefix = "with_")]
#[serde(rename_all = "camelCase")]
pub struct GetChartRangeRequestRequest {
pub info: ChartRangeInfoRecord,
}
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize, Setters)]
#[setters(into, strip_option, prefix = "with_")]
#[serde(rename_all = "camelCase")]
pub struct ChartRangeInfoRecord {
pub end: u64,
pub period: TimePeriod,
pub start: u64,
pub symbol: String,
pub ticks: Option<i64>,
}
pub type GetChartRangeRequestResponse = GetChartLastRequestResponse;
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize, Setters)]
#[setters(into, strip_option, prefix = "with_")]
#[serde(rename_all = "camelCase")]
pub struct GetCommissionDefRequest {
pub symbol: String,
pub volume: Decimal,
}
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize, Setters)]
#[setters(into, strip_option, prefix = "with_")]
#[serde(rename_all = "camelCase")]
pub struct GetCommissionDefResponse {
commission: Option<Decimal>,
rate_of_exchange: Option<Decimal>,
}
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize)]
pub struct GetCurrentUserDataRequest;
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize, Setters)]
#[setters(into, strip_option, prefix = "with_")]
#[serde(rename_all = "camelCase")]
pub struct GetCurrentUserDataResponse {
pub company_unit: i64,
pub currency: String,
pub group: String,
pub ib_account: bool,
pub leverage: i64,
pub leverage_multiplier: Decimal,
pub spread_type: Option<String>,
pub trailing_stop: bool,
}
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize, Setters)]
#[setters(into, strip_option, prefix = "with_")]
#[serde(rename_all = "camelCase")]
pub struct GetIbsHistoryRequest {
pub end: u64,
pub start: u64,
}
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize)]
pub struct GetIbsHistoryResponse(Vec<IBRecord>);
impl Deref for GetIbsHistoryResponse {
type Target = Vec<IBRecord>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for GetIbsHistoryResponse {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize, Setters)]
#[setters(into, strip_option, prefix = "with_")]
#[serde(rename_all = "camelCase")]
pub struct IBRecord {
pub close_price: Option<Decimal>,
pub login: Option<String>,
pub nominal: Option<Decimal>,
pub open_price: Option<Decimal>,
pub side: Option<TradingAction>,
pub surname: Option<String>,
pub symbol: Option<String>,
pub timestamp: Option<u64>,
pub volume: Option<Decimal>,
}
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize)]
pub struct GetMarginLevelRequest;
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize, Setters)]
#[setters(into, strip_option, prefix = "with_")]
#[serde(rename_all = "camelCase")]
pub struct GetMarginLevelResponse {
pub balance: Decimal,
pub credit: Decimal,
pub currency: String,
pub equity: Decimal,
pub margin: Decimal,
#[serde(rename = "margin_free")]
pub margin_free: Decimal,
#[serde(rename = "margin_level")]
pub margin_level: Decimal,
}
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize, Setters)]
#[setters(into, strip_option, prefix = "with_")]
#[serde(rename_all = "camelCase")]
pub struct GetMarginTradeRequest {
pub symbol: String,
pub volume: Decimal,
}
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize, Setters)]
#[setters(into, strip_option, prefix = "with_")]
#[serde(rename_all = "camelCase")]
pub struct GetMarginTradeResponse {
pub margin: Decimal,
}
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize, Setters)]
#[setters(into, strip_option, prefix = "with_")]
#[serde(rename_all = "camelCase")]
pub struct GetNewsRequest {
pub end: u64,
pub start: u64,
}
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize)]
pub struct GetNewsResponse(Vec<NewsBodyRecord>);
impl Deref for GetNewsResponse {
type Target = Vec<NewsBodyRecord>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for GetNewsResponse {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize, Setters)]
#[setters(into, strip_option, prefix = "with_")]
#[serde(rename_all = "camelCase")]
pub struct NewsBodyRecord {
pub body: String,
#[serde(rename = "bodylen")]
pub body_len: usize,
pub key: String,
pub time: u64,
pub time_string: String,
pub title: String,
}
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize, Setters)]
#[setters(into, strip_option, prefix = "with_")]
#[serde(rename_all = "camelCase")]
pub struct GetProfitCalculationRequest {
pub close_price: Decimal,
pub cmd: TradingCommand,
pub open_price: Decimal,
pub symbol: String,
pub volume: Decimal,
}
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize, Setters)]
#[setters(into, strip_option, prefix = "with_")]
#[serde(rename_all = "camelCase")]
pub struct GetProfitCalculationResponse {
pub profit: Decimal,
}
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize)]
pub struct GetServerTimeRequest;
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize, Setters)]
#[setters(into, strip_option, prefix = "with_")]
#[serde(rename_all = "camelCase")]
pub struct GetServerTimeResponse {
pub time: u64,
pub time_string: String,
}
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize)]
pub struct GetStepRulesRequest;
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize)]
pub struct GetStepRulesResponse(Vec<StepRuleRecord>);
impl Deref for GetStepRulesResponse {
type Target = Vec<StepRuleRecord>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for GetStepRulesResponse {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize, Setters)]
#[setters(into, strip_option, prefix = "with_")]
#[serde(rename_all = "camelCase")]
pub struct StepRuleRecord {
pub id: u32,
pub name: String,
pub steps: Vec<StepRecord>,
}
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize, Setters)]
#[setters(into, strip_option, prefix = "with_")]
#[serde(rename_all = "camelCase")]
pub struct StepRecord {
pub from_value: Decimal,
pub step: Decimal,
}
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize, Setters)]
#[setters(into, strip_option, prefix = "with_")]
#[serde(rename_all = "camelCase")]
pub struct GetSymbolRequest {
pub symbol: String,
}
pub type GetSymbolResponse = SymbolRecord;
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize, Setters)]
#[setters(into, strip_option, prefix = "with_")]
#[serde(rename_all = "camelCase")]
pub struct GetTickPricesRequest {
pub level: u32,
pub symbols: Vec<String>,
pub timestamp: u64,
}
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize, Setters)]
#[setters(into, strip_option, prefix = "with_")]
#[serde(rename_all = "camelCase")]
pub struct GetTickPricesResponse {
pub quotations: Vec<TickRecord>,
}
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize, Setters)]
#[setters(into, strip_option, prefix = "with_")]
#[serde(rename_all = "camelCase")]
pub struct TickRecord {
pub ask: Decimal,
pub ask_volume: Option<u32>,
pub bid: Decimal,
pub bid_volume: Option<u32>,
pub high: Decimal,
pub level: u32,
pub low: Decimal,
pub spread_raw: Decimal,
pub spread_table: Decimal,
pub symbol: String,
pub timestamp: u64,
}
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize, Setters)]
#[setters(into, strip_option, prefix = "with_")]
#[serde(rename_all = "camelCase")]
pub struct GetTradeRecordsRequest {
pub orders: Vec<u32>,
}
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize)]
pub struct GetTradeRecordsResponse(Vec<TradeRecord>);
impl Deref for GetTradeRecordsResponse {
type Target = Vec<TradeRecord>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for GetTradeRecordsResponse {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize, Setters)]
#[setters(into, strip_option, prefix = "with_")]
#[serde(rename_all = "camelCase")]
pub struct TradeRecord {
#[serde(rename = "close_price")]
pub close_price: Decimal,
#[serde(rename = "close_time")]
pub close_time: Option<u64>,
#[serde(rename="close_timeString")]
pub close_time_string: Option<String>,
pub closed: bool,
pub cmd: TradingCommand,
pub comment: String,
pub commission: Option<Decimal>,
pub custom_comment: String,
pub digits: u32,
pub expiration: Option<u64>,
pub expiration_string: Option<String>,
#[serde(rename = "margin_rate")]
pub margin_rate: Decimal,
pub offset: u32,
#[serde(rename = "open_price")]
pub open_price: Decimal,
#[serde(rename = "open_time")]
pub open_time: u64,
#[serde(rename = "open_timeString")]
pub open_time_string: String,
pub order: u32,
pub order2: u32,
pub position: u32,
pub profit: Decimal,
pub sl: Decimal,
pub storage: Decimal,
pub symbol: Option<String>,
pub timestamp: u64,
pub tp: Decimal,
pub volume: Decimal,
}
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize, Setters)]
#[setters(into, strip_option, prefix = "with_")]
#[serde(rename_all = "camelCase")]
pub struct GetTradesRequest {
pub opened_only: bool,
}
pub type GetTradesResponse = GetTradeRecordsResponse;
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize, Setters)]
#[setters(into, strip_option, prefix = "with_")]
#[serde(rename_all = "camelCase")]
pub struct GetTradesHistoryRequest {
pub end: u64,
pub start: u64,
}
pub type GetTradesHistoryResponse = GetTradeRecordsResponse;
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize, Setters)]
#[setters(into, strip_option, prefix = "with_")]
#[serde(rename_all = "camelCase")]
pub struct GetTradingHoursRequest {
pub symbols: Vec<String>,
}
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize)]
pub struct GetTradingHoursResponse(Vec<TradingHoursRecord>);
impl Deref for GetTradingHoursResponse {
type Target = Vec<TradingHoursRecord>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for GetTradingHoursResponse {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize, Setters)]
#[setters(into, strip_option, prefix = "with_")]
#[serde(rename_all = "camelCase")]
pub struct TradingHoursRecord {
pub quotes: Vec<HoursRecord>,
pub symbol: String,
pub trading: Vec<HoursRecord>,
}
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize, Setters)]
#[setters(into, strip_option, prefix = "with_")]
#[serde(rename_all = "camelCase")]
pub struct HoursRecord {
pub day: u8,
pub from_t: u64,
pub to_t: u64,
}
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize)]
pub struct GetVersionRequest;
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize, Setters)]
#[setters(into, strip_option, prefix = "with_")]
#[serde(rename_all = "camelCase")]
pub struct GetVersionResponse {
pub version: String,
}
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize)]
pub struct PingRequest;
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize)]
pub struct PingResponse;
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize, Setters)]
#[setters(into, strip_option, prefix = "with_")]
#[serde(rename_all = "camelCase")]
pub struct TradeTransactionRequest {
pub trade_trans_info: TradeTransInfo,
}
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize, Setters)]
#[setters(into, strip_option, prefix = "with_")]
#[serde(rename_all = "camelCase")]
pub struct TradeTransInfo {
pub cmd: TradingCommand,
pub custom_comment: String,
pub expiration: u64,
pub offset: i32,
pub order: i32,
pub price: f64,
pub sl: f64,
pub symbol: String,
pub tp: f64,
pub type_: TransactionType,
pub volume: f64,
}
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize, Setters)]
#[setters(into, strip_option, prefix = "with_")]
#[serde(rename_all = "camelCase")]
pub struct TradeTransactionResponse {
pub order: i32,
}
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize, Setters)]
#[setters(into, strip_option, prefix = "with_")]
#[serde(rename_all = "camelCase")]
pub struct TradeTransactionStatusRequest {
pub order: i32,
}
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize, Setters)]
#[setters(into, strip_option, prefix = "with_")]
#[serde(rename_all = "camelCase")]
pub struct TradeTransactionStatusResponse {
pub ask: f64,
pub bid: f64,
pub custom_comment: String,
pub message: Option<String>,
pub order: i32,
pub request_status: TransactionStatus,
}
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize)]
pub struct StreamGetBalanceSubscribe;
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize)]
pub struct StreamGetBalanceUnsubscribe;
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize, Setters)]
#[setters(into, strip_option, prefix = "with_")]
#[serde(rename_all = "camelCase")]
pub struct StreamGetBalanceData {
pub balance: f64,
pub credit: f64,
pub equity: f64,
pub margin: f64,
pub margin_free: f64,
pub margin_level: f64,
}
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize, Setters)]
#[setters(into, strip_option, prefix = "with_")]
#[serde(rename_all = "camelCase")]
pub struct StreamGetCandlesSubscribe {
pub symbol: String,
}
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize, Setters)]
#[setters(into, strip_option, prefix = "with_")]
#[serde(rename_all = "camelCase")]
pub struct StreamGetCandlesUnsubscribe {
pub symbol: String,
}
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize, Setters)]
#[setters(into, strip_option, prefix = "with_")]
#[serde(rename_all = "camelCase")]
pub struct StreamGetCandlesData {
pub close: f64,
pub ctm: u64,
pub ctm_string: String,
pub high: f64,
pub low: f64,
pub open: f64,
pub quote_id: QuoteId,
pub symbol: String,
pub vol: f64,
}
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize)]
pub struct StreamGetKeepAliveSubscribe;
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize)]
pub struct StreamGetKeepAliveUnsubscribe;
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize, Setters)]
#[setters(into, strip_option, prefix = "with_")]
#[serde(rename_all = "camelCase")]
pub struct StreamGetKeepAliveData {
pub timestamp: u64,
}
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize)]
pub struct StreamGetNewsSubscribe;
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize)]
pub struct StreamGetNewsUnsubscribe;
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize, Setters)]
#[setters(into, strip_option, prefix = "with_")]
#[serde(rename_all = "camelCase")]
pub struct StreamGetNewsData {
pub body: String,
pub key: String,
pub time: u64,
pub title: String,
}
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize)]
pub struct StreamGetProfitSubscribe;
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize)]
pub struct StreamGetProfitUnsubscribe;
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize, Setters)]
#[setters(into, strip_option, prefix = "with_")]
#[serde(rename_all = "camelCase")]
pub struct StreamGetProfitData {
pub order: i32,
pub order2: i32,
pub position: i32,
pub profit: f64,
}
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize, Setters)]
#[setters(into, strip_option, prefix = "with_")]
#[serde(rename_all = "camelCase")]
pub struct StreamGetTickPricesSubscribe {
pub symbol: String,
pub min_arrival_time: Option<u64>,
pub max_level: Option<u64>,
}
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize, Setters)]
#[setters(into, strip_option, prefix = "with_")]
#[serde(rename_all = "camelCase")]
pub struct StreamGetTickPricesUnsubscribe {
pub symbol: String,
}
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize, Setters)]
#[setters(into, strip_option, prefix = "with_")]
#[serde(rename_all = "camelCase")]
pub struct StreamGetTickPricesData {
pub ask: f64,
pub ask_volume: Option<i32>,
pub bid: f64,
pub bid_volume: Option<i32>,
pub high: f64,
pub level: i32,
pub low: f64,
pub quote_id: QuoteId,
pub spread_raw: f64,
pub spread_table: f64,
pub symbol: String,
pub timestamp: u64,
}
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize)]
pub struct StreamGetTradesSubscribe;
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize)]
pub struct StreamGetTradesUnsubscribe;
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize, Setters)]
#[setters(into, strip_option, prefix = "with_")]
#[serde(rename_all = "camelCase")]
pub struct StreamGetTradesData {
#[serde(rename = "close_price")]
pub close_price: f64,
#[serde(rename = "close_time")]
pub close_time: Option<u64>,
pub closed: bool,
pub cmd: TradingCommand,
pub comment: String,
pub commission: Option<f64>,
pub custom_comment: String,
pub digits: i32,
pub expiration: Option<u64>,
#[serde(rename = "margin_rate")]
pub margin_rate: f64,
pub offset: i32,
#[serde(rename = "open_price")]
pub open_price: f64,
#[serde(rename = "open_time")]
pub open_time: u64,
pub order: i32,
pub order2: i32,
pub position: i32,
pub profit: Option<f64>,
pub sl: f64,
pub state: TradeStatus,
pub storage: f64,
pub symbol: String,
pub tp: f64,
pub type_: TransactionType,
pub volume: f64,
}
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize)]
pub struct StreamGetTradeStatusSubscribe;
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize)]
pub struct StreamGetTradeStatusUnsubscribe;
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize, Setters)]
#[setters(into, strip_option, prefix = "with_")]
#[serde(rename_all = "camelCase")]
pub struct StreamGetTradeStatusData {
pub custom_comment: String,
pub message: Option<String>,
pub order: i32,
pub price: f64,
pub request_status: TransactionStatus,
}
#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize)]
pub struct StreamPingSubscribe;
#[cfg(test)]
mod tests {
use serde_json::Value;
fn assert_all_keys(value: &Value, keys: Vec<&str>) {
assert!(value.is_object());
let Value::Object(mapping) = value else { unreachable!() };
let extra_keys: Vec<_> = mapping.keys().filter(|k| !keys.contains(&k.as_str())).map(|k| k.to_owned()).collect();
let missing_keys: Vec<_> = keys.into_iter().filter(|k| !mapping.contains_key(k.to_string().as_str())).map(|k| k.to_owned()).collect();
if !extra_keys.is_empty() || !missing_keys.is_empty() {
panic!("Keys in value does not match to expected keys.\nExtra keys: {:?}\nMissing keys: {:?}", extra_keys, missing_keys);
}
}
mod serialize_deserialize {
use std::fmt::Debug;
use std::ops::Deref;
use rstest::rstest;
use serde::{Deserialize, Serialize};
use serde_json::{from_str, from_value, to_string, to_value};
use crate::schema::data::{GetTickPricesResponse, StreamPingSubscribe, StreamGetTradeStatusSubscribe, StreamGetTradeStatusUnsubscribe, StreamGetTradesData, StreamGetTradesSubscribe, StreamGetTradesUnsubscribe, StreamGetTickPricesSubscribe, StreamGetTickPricesUnsubscribe, StreamGetTickPricesData, StreamGetProfitData, StreamGetProfitSubscribe, StreamGetProfitUnsubscribe, StreamGetKeepAliveData, StreamGetNewsSubscribe, StreamGetNewsData, StreamGetNewsUnsubscribe, StreamGetKeepAliveSubscribe, StreamGetKeepAliveUnsubscribe, StreamGetCandlesSubscribe, StreamGetCandlesUnsubscribe, StreamGetBalanceData, StreamGetCandlesData, StreamGetBalanceSubscribe, StreamGetBalanceUnsubscribe, TradeTransactionStatusResponse, TradeTransactionStatusRequest, TradeTransactionResponse, TradeTransInfo, TradeTransactionRequest, GetVersionResponse, PingRequest, PingResponse, GetVersionRequest, TradingHoursRecord, HoursRecord, GetTradingHoursResponse, GetTradingHoursRequest, GetTradesHistoryRequest, GetTradesRequest, GetTradeRecordsResponse, TradeRecord, GetTradeRecordsRequest, TickRecord, GetTickPricesRequest, GetSymbolRequest, GetStepRulesResponse, StepRuleRecord, StepRecord, GetStepRulesRequest, GetServerTimeRequest, GetServerTimeResponse, GetProfitCalculationRequest, GetProfitCalculationResponse, GetNewsRequest, GetNewsResponse, NewsBodyRecord, GetMarginTradeRequest, GetMarginTradeResponse, GetMarginLevelRequest, GetMarginLevelResponse, IBRecord, GetIbsHistoryResponse, GetCurrentUserDataResponse, GetCurrentUserDataRequest, GetCommissionDefRequest, GetCommissionDefResponse, GetChartRangeRequestRequest, ChartRangeInfoRecord, GetChartLastRequestResponse, RateInfoRecord, ChartLastInfoRecord, GetChartLastRequestRequest, GetCalendarResponse, CalendarRecord, GetAllSymbolsRequest, GetAllSymbolsResponse, LoginRequest, LoginResponse, SymbolRecord, GetCalendarRequest, StreamGetTradeStatusData};
use crate::schema::data::tests::assert_all_keys;
#[rstest]
#[case::LoginRequest_1(LoginRequest::default(), vec ! ["userId", "password"])]
#[case::LoginRequest_2(LoginRequest::default().with_app_id("foo").with_app_name("bar"), vec ! ["userId", "password", "appId", "appName"])]
#[case::SymbolRecord_1(SymbolRecord::default(), vec ! ["ask", "bid", "categoryName", "contractSize", "currency", "currencyPair", "currencyProfit", "description", "expiration", "groupName", "high", "initialMargin", "instantMaxVolume", "leverage", "longOnly", "lotMax", "lotMin", "lotStep", "low", "marginHedged", "marginHedgedStrong", "marginMaintenance", "marginMode", "percentage", "pipsPrecision", "precision", "profitMode", "quoteId", "shortSelling", "spreadRaw", "spreadTable", "starting", "stepRuleId", "stopsLevel", "swap_rollover3days", "swapEnable", "swapLong", "swapShort", "swapType", "symbol", "tickSize", "tickValue", "time", "timeString", "trailingEnabled", "type"])]
#[case::CalendarRecord_1(CalendarRecord::default(), vec!["country", "current", "forecast", "impact", "period", "previous", "time", "title"])]
#[case::GetChartLastRequestRequest_1(GetChartLastRequestRequest::default(), vec!["info"])]
#[case::ChartLastInfoRecord_1(ChartLastInfoRecord::default(), vec!["period", "start", "symbol"])]
#[case::GetChartLastRequestResponse_1(GetChartLastRequestResponse::default(), vec!["digits", "rateInfos"])]
#[case::RateInfoRecord_1(RateInfoRecord::default(), vec!["close", "ctm", "ctmString", "high", "low", "open", "vol"])]
#[case::GetChartRangeRequestRequest_1(GetChartRangeRequestRequest::default(), vec!["info"])]
#[case::ChartRangeInfoRecord_1(ChartRangeInfoRecord::default(), vec!["end", "period", "start", "symbol", "ticks"])]
#[case::GetCommissionDefRequest_1(GetCommissionDefRequest::default(), vec!["symbol", "volume"])]
#[case::GetCommissionDefResponse_1(GetCommissionDefResponse::default(), vec!["commission", "rateOfExchange"])]
#[case::GetCurrentUserDataResponse_1(GetCurrentUserDataResponse::default(), vec!["companyUnit", "currency", "group", "ibAccount", "leverage", "leverageMultiplier", "spreadType", "trailingStop"])]
#[case::IBRecord_1(IBRecord::default(), vec!["closePrice", "login", "nominal", "openPrice", "side", "surname", "symbol", "timestamp", "volume"])]
#[case::GetMarginLevelResponse_1(GetMarginLevelResponse::default(), vec!["balance", "credit", "currency", "equity", "margin", "margin_free", "margin_level"])]
#[case::GetMarginTradeRequest_1(GetMarginTradeRequest::default(), vec!["symbol", "volume"])]
#[case::GetMarginTradeResponse_1(GetMarginTradeResponse::default(), vec!["margin"])]
#[case::GetNewsRequest_1(GetNewsRequest::default(), vec!["end", "start"])]
#[case::NewsBodyRecord_1(NewsBodyRecord::default(), vec!["body", "bodylen", "key", "time", "timeString", "title"])]
#[case::GetProfitCalculationRequest_1(GetProfitCalculationRequest::default(), vec!["closePrice", "cmd", "openPrice", "symbol", "volume"])]
#[case::GetProfitCalculationResponse_1(GetProfitCalculationResponse::default(), vec!["profit"])]
#[case::GetServerTimeResponse_1(GetServerTimeResponse::default(), vec!["time", "timeString"])]
#[case::StepRuleRecord_1(StepRuleRecord::default(), vec!["id", "name", "steps"])]
#[case::StepRecord_1(StepRecord::default(), vec!["fromValue", "step"])]
#[case::GetSymbolRequest_1(GetSymbolRequest::default(), vec!["symbol"])]
#[case::GetTickPricesRequest_1(GetTickPricesRequest::default(), vec!["level", "symbols", "timestamp"])]
#[case::GetTickPricesResponse_1(GetTickPricesResponse::default(), vec!["quotations"])]
#[case::TickRecord_1(TickRecord::default(), vec!["ask", "askVolume", "bid", "bidVolume", "high", "level", "low", "spreadRaw", "spreadTable", "symbol", "timestamp"])]
#[case::GetTradeRecordsRequest_1(GetTradeRecordsRequest::default(), vec!["orders"])]
#[case::TradeRecord_1(TradeRecord::default(), vec!["close_price", "close_time", "close_timeString", "closed", "cmd", "comment", "commission", "customComment", "digits", "expiration", "expirationString", "margin_rate", "offset", "open_price", "open_time", "open_timeString", "order", "order2", "position", "profit", "sl", "storage", "symbol", "timestamp", "tp", "volume"])]
#[case::GetTradesRequest_1(GetTradesRequest::default(), vec!["openedOnly"])]
#[case::GetTradesHistoryRequest_1(GetTradesHistoryRequest::default(), vec!["end", "start"])]
#[case::GetTradingHoursRequest_1(GetTradingHoursRequest::default(), vec!["symbols"])]
#[case::TradingHoursRecord_1(TradingHoursRecord::default(), vec!["quotes", "symbol", "trading"])]
#[case::HoursRecord_1(HoursRecord::default(), vec!["day", "fromT", "toT"])]
#[case::GetVersionResponse_1(GetVersionResponse::default(), vec!["version"])]
#[case::TradeTransactionRequest_1(TradeTransactionRequest::default(), vec!["tradeTransInfo"])]
#[case::TradeTransInfo_1(TradeTransInfo::default(), vec!["cmd", "customComment", "expiration", "offset", "order", "price", "sl", "symbol", "tp", "type", "volume"])]
#[case::TradeTransactionResponse_1(TradeTransactionResponse::default(), vec!["order"])]
#[case::TradeTransactionStatusRequest_1(TradeTransactionStatusRequest::default(), vec!["order"])]
#[case::TradeTransactionStatusResponse_1(TradeTransactionStatusResponse::default(), vec!["ask", "bid", "customComment", "message", "order", "requestStatus"])]
#[case::StreamGetBalanceData_1(StreamGetBalanceData::default(), vec!["balance", "credit", "equity", "margin", "marginFree", "marginLevel"])]
#[case::StreamGetCandlesData_1(StreamGetCandlesData::default(), vec!["close", "ctm", "ctmString", "high", "low", "open", "quoteId", "symbol", "vol"])]
#[case::StreamGetCandlesSubscribe_1(StreamGetCandlesSubscribe::default(), vec!["symbol"])]
#[case::StreamGetCandlesUnsubscribe_1(StreamGetCandlesUnsubscribe::default(), vec!["symbol"])]
#[case::StreamGetKeepAliveData_1(StreamGetKeepAliveData::default(), vec!["timestamp"])]
#[case::StreamGetNewsData_1(StreamGetNewsData::default(), vec!["body", "key", "time", "title"])]
#[case::StreamGetProfitData_1(StreamGetProfitData::default(), vec!["order", "order2", "position", "profit"])]
#[case::StreamGetTickPricesSubscribe_1(StreamGetTickPricesSubscribe::default(), vec!["symbol", "minArrivalTime", "maxLevel"])]
#[case::StreamGetTickPricesUnsubscribe_1(StreamGetTickPricesUnsubscribe::default(), vec!["symbol"])]
#[case::StreamGetTickPricesData_1(StreamGetTickPricesData::default(), vec!["ask", "askVolume", "bid", "bidVolume", "high", "level", "low", "quoteId", "spreadRaw", "spreadTable", "symbol", "timestamp"])]
#[case::StreamGetTradesData_1(StreamGetTradesData::default(), vec!["close_price", "close_time", "closed", "cmd", "comment", "commission", "customComment", "digits", "expiration", "margin_rate", "offset", "open_price", "open_time", "order", "order2", "position", "profit", "sl", "state", "storage", "symbol", "tp", "type", "volume"])]
#[case::StreamGetTradeStatusData_1(StreamGetTradeStatusData::default(), vec!["customComment", "message", "order", "price", "requestStatus"])]
fn serialize_deserialize_payload_struct<T: Serialize + Clone + Default + Debug + PartialEq + for<'de> Deserialize<'de>>(#[case] original: T, #[case] keys: Vec<&str>) {
let serialized_value = to_value(original.clone()).unwrap();
assert_all_keys(&serialized_value, keys);
let new_value = from_value(serialized_value).unwrap();
assert_eq!(original, new_value);
}
#[rstest]
#[case::LoginResponse_1(LoginResponse)]
#[case::GetAllSymbolsRequest_1(GetAllSymbolsRequest)]
#[case::GetCalendarRequest_1(GetCalendarRequest)]
#[case::GetCalendarRequest_1(GetCurrentUserDataRequest)]
#[case::GetMarginLevelRequest_1(GetMarginLevelRequest)]
#[case::GetServerTimeRequest_1(GetServerTimeRequest)]
#[case::GetStepRulesRequest_1(GetStepRulesRequest)]
#[case::GetVersionRequest_1(GetVersionRequest)]
#[case::PingRequest_1(PingRequest)]
#[case::PingResponse_1(PingResponse)]
#[case::StreamGetBalanceSubscribe_1(StreamGetBalanceSubscribe)]
#[case::StreamGetBalanceUnsubscribe_1(StreamGetBalanceUnsubscribe)]
#[case::StreamGetKeepAliveSubscribe_1(StreamGetKeepAliveSubscribe)]
#[case::StreamGetKeepAliveUnsubscribe_1(StreamGetKeepAliveUnsubscribe)]
#[case::StreamGetNewsSubscribe_1(StreamGetNewsSubscribe)]
#[case::StreamGetNewsUnsubscribe_1(StreamGetNewsUnsubscribe)]
#[case::StreamGetProfitSubscribe_1(StreamGetProfitSubscribe)]
#[case::StreamGetProfitUnsubscribe_1(StreamGetProfitUnsubscribe)]
#[case::StreamGetTradesSubscribe_1(StreamGetTradesSubscribe)]
#[case::StreamGetTradesUnsubscribe_1(StreamGetTradesUnsubscribe)]
#[case::StreamGetTradeStatusSubscribe_1(StreamGetTradeStatusSubscribe)]
#[case::StreamGetTradeStatusUnsubscribe_1(StreamGetTradeStatusUnsubscribe)]
#[case::StreamPingSubscribe_1(StreamPingSubscribe)]
fn serialize_deserialize_logic_struct<T: Serialize + Clone + Default + Debug + PartialEq + for<'de> Deserialize<'de>>(#[case] original: T) {
let serialized_value = to_value(original.clone()).unwrap();
assert!(serialized_value.is_null());
let new_value = from_value(serialized_value).unwrap();
assert_eq!(original, new_value);
}
#[rstest]
#[case::GetAllSymbolsResponse_1(GetAllSymbolsResponse::default())]
#[case::GetCalendarResponse_1(GetCalendarResponse::default())]
#[case::GetIbsHistoryResponse_1(GetIbsHistoryResponse::default())]
#[case::GetNewsResponse_1(GetNewsResponse::default())]
#[case::GetStepRulesResponse_1(GetStepRulesResponse::default())]
#[case::GetTradeRecordsResponse_1(GetTradeRecordsResponse::default())]
#[case::GetTradingHoursResponse_1(GetTradingHoursResponse::default())]
fn deserialize_empty_array_of_records<T: Serialize + for<'de> Deserialize<'de> + PartialEq + Debug>(#[case] reference: T) {
let response: T = from_str("[]").unwrap();
let serialized_reference = to_string(&reference).unwrap();
assert_eq!(response, reference);
assert_eq!(&serialized_reference, "[]");
}
#[rstest]
#[case::GetAllSymbolsResponse_1(GetAllSymbolsResponse::default())]
#[case::GetCalendarResponse_1(GetCalendarResponse::default())]
#[case::GetIbsHistoryResponse_1(GetIbsHistoryResponse::default())]
#[case::GetNewsResponse_1(GetNewsResponse::default())]
#[case::GetStepRulesResponse_1(GetStepRulesResponse::default())]
#[case::GetTradeRecordsResponse_1(GetTradeRecordsResponse::default())]
#[case::GetTradingHoursResponse_1(GetTradingHoursResponse::default())]
fn deserialize_array_of_records_with_one_record<T, I>(#[case] inp: T)
where
T: Serialize + for<'de> Deserialize<'de> + PartialEq + Debug + Deref<Target = Vec<I>>,
I: Default + PartialEq + Debug + Serialize + for<'de> Deserialize<'de>
{
let ref_val = SymbolRecord::default();
let source_data = format!("[{}]", to_string(&ref_val).unwrap());
let response: GetAllSymbolsResponse = from_str(&source_data).unwrap();
assert_eq!(response.len(), 1);
assert_eq!(response[0], ref_val);
}
}
}