/*
 * Binance Derivatives Trading COIN Futures REST API
 *
 * OpenAPI Specification for the Binance Derivatives Trading COIN Futures REST API
 *
 * The version of the OpenAPI document: 1.0.0
 *
 *
 * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
 * https://openapi-generator.tech
 * Do not edit the class manually.
 */

#![allow(unused_imports)]
use async_trait::async_trait;
use derive_builder::Builder;
use reqwest;
use rust_decimal::prelude::*;
use serde::{Deserialize, Serialize};
use serde_json::{Value, json};
use std::collections::BTreeMap;

use crate::common::{
    config::ConfigurationRestApi,
    models::{ParamBuildError, RestApiResponse},
    utils::send_request,
};
use crate::derivatives_trading_coin_futures::rest_api::models;

const HAS_TIME_UNIT: bool = false;

#[async_trait]
pub trait MarketDataApi: Send + Sync {
    async fn basis(
        &self,
        params: BasisParams,
    ) -> anyhow::Result<RestApiResponse<Vec<models::BasisResponseInner>>>;
    async fn check_server_time(
        &self,
    ) -> anyhow::Result<RestApiResponse<models::CheckServerTimeResponse>>;
    async fn compressed_aggregate_trades_list(
        &self,
        params: CompressedAggregateTradesListParams,
    ) -> anyhow::Result<RestApiResponse<Vec<models::CompressedAggregateTradesListResponseInner>>>;
    async fn continuous_contract_kline_candlestick_data(
        &self,
        params: ContinuousContractKlineCandlestickDataParams,
    ) -> anyhow::Result<
        RestApiResponse<Vec<Vec<models::ContinuousContractKlineCandlestickDataResponseItemInner>>>,
    >;
    async fn exchange_information(
        &self,
    ) -> anyhow::Result<RestApiResponse<models::ExchangeInformationResponse>>;
    async fn get_funding_rate_history_of_perpetual_futures(
        &self,
        params: GetFundingRateHistoryOfPerpetualFuturesParams,
    ) -> anyhow::Result<
        RestApiResponse<Vec<models::GetFundingRateHistoryOfPerpetualFuturesResponseInner>>,
    >;
    async fn get_funding_rate_info(
        &self,
    ) -> anyhow::Result<RestApiResponse<Vec<models::GetFundingRateInfoResponseInner>>>;
    async fn index_price_and_mark_price(
        &self,
        params: IndexPriceAndMarkPriceParams,
    ) -> anyhow::Result<RestApiResponse<Vec<models::IndexPriceAndMarkPriceResponseInner>>>;
    async fn index_price_kline_candlestick_data(
        &self,
        params: IndexPriceKlineCandlestickDataParams,
    ) -> anyhow::Result<
        RestApiResponse<Vec<Vec<models::IndexPriceKlineCandlestickDataResponseItemInner>>>,
    >;
    async fn kline_candlestick_data(
        &self,
        params: KlineCandlestickDataParams,
    ) -> anyhow::Result<
        RestApiResponse<Vec<Vec<models::ContinuousContractKlineCandlestickDataResponseItemInner>>>,
    >;
    async fn long_short_ratio(
        &self,
        params: LongShortRatioParams,
    ) -> anyhow::Result<RestApiResponse<Vec<models::LongShortRatioResponseInner>>>;
    async fn mark_price_kline_candlestick_data(
        &self,
        params: MarkPriceKlineCandlestickDataParams,
    ) -> anyhow::Result<
        RestApiResponse<Vec<Vec<models::MarkPriceKlineCandlestickDataResponseItemInner>>>,
    >;
    async fn old_trades_lookup(
        &self,
        params: OldTradesLookupParams,
    ) -> anyhow::Result<RestApiResponse<Vec<models::OldTradesLookupResponseInner>>>;
    async fn open_interest(
        &self,
        params: OpenInterestParams,
    ) -> anyhow::Result<RestApiResponse<models::OpenInterestResponse>>;
    async fn open_interest_statistics(
        &self,
        params: OpenInterestStatisticsParams,
    ) -> anyhow::Result<RestApiResponse<Vec<models::OpenInterestStatisticsResponseInner>>>;
    async fn order_book(
        &self,
        params: OrderBookParams,
    ) -> anyhow::Result<RestApiResponse<models::OrderBookResponse>>;
    async fn premium_index_kline_data(
        &self,
        params: PremiumIndexKlineDataParams,
    ) -> anyhow::Result<RestApiResponse<Vec<Vec<models::PremiumIndexKlineDataResponseItemInner>>>>;
    async fn query_index_price_constituents(
        &self,
        params: QueryIndexPriceConstituentsParams,
    ) -> anyhow::Result<RestApiResponse<models::QueryIndexPriceConstituentsResponse>>;
    async fn recent_trades_list(
        &self,
        params: RecentTradesListParams,
    ) -> anyhow::Result<RestApiResponse<Vec<models::RecentTradesListResponseInner>>>;
    async fn symbol_order_book_ticker(
        &self,
        params: SymbolOrderBookTickerParams,
    ) -> anyhow::Result<RestApiResponse<Vec<models::SymbolOrderBookTickerResponseInner>>>;
    async fn symbol_price_ticker(
        &self,
        params: SymbolPriceTickerParams,
    ) -> anyhow::Result<RestApiResponse<Vec<models::SymbolPriceTickerResponseInner>>>;
    async fn taker_buy_sell_volume(
        &self,
        params: TakerBuySellVolumeParams,
    ) -> anyhow::Result<RestApiResponse<Vec<models::TakerBuySellVolumeResponseInner>>>;
    async fn test_connectivity(&self) -> anyhow::Result<RestApiResponse<Value>>;
    async fn ticker24hr_price_change_statistics(
        &self,
        params: Ticker24hrPriceChangeStatisticsParams,
    ) -> anyhow::Result<RestApiResponse<Vec<models::Ticker24hrPriceChangeStatisticsResponseInner>>>;
    async fn top_trader_long_short_ratio_accounts(
        &self,
        params: TopTraderLongShortRatioAccountsParams,
    ) -> anyhow::Result<RestApiResponse<Vec<models::TopTraderLongShortRatioAccountsResponseInner>>>;
    async fn top_trader_long_short_ratio_positions(
        &self,
        params: TopTraderLongShortRatioPositionsParams,
    ) -> anyhow::Result<RestApiResponse<Vec<models::TopTraderLongShortRatioPositionsResponseInner>>>;
}

#[derive(Debug, Clone)]
pub struct MarketDataApiClient {
    configuration: ConfigurationRestApi,
}

impl MarketDataApiClient {
    pub fn new(configuration: ConfigurationRestApi) -> Self {
        Self { configuration }
    }
}

#[allow(non_camel_case_types)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum BasisContractTypeEnum {
    #[serde(rename = "PERPETUAL")]
    Perpetual,
    #[serde(rename = "CURRENT_QUARTER")]
    CurrentQuarter,
    #[serde(rename = "NEXT_QUARTER")]
    NextQuarter,
    #[serde(rename = "CURRENT_QUARTER_DELIVERING")]
    CurrentQuarterDelivering,
    #[serde(rename = "NEXT_QUARTER_DELIVERING")]
    NextQuarterDelivering,
    #[serde(rename = "PERPETUAL_DELIVERING")]
    PerpetualDelivering,
}

impl BasisContractTypeEnum {
    #[must_use]
    pub fn as_str(&self) -> &'static str {
        match self {
            Self::Perpetual => "PERPETUAL",
            Self::CurrentQuarter => "CURRENT_QUARTER",
            Self::NextQuarter => "NEXT_QUARTER",
            Self::CurrentQuarterDelivering => "CURRENT_QUARTER_DELIVERING",
            Self::NextQuarterDelivering => "NEXT_QUARTER_DELIVERING",
            Self::PerpetualDelivering => "PERPETUAL_DELIVERING",
        }
    }
}

impl std::str::FromStr for BasisContractTypeEnum {
    type Err = Box<dyn std::error::Error + Send + Sync>;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "PERPETUAL" => Ok(Self::Perpetual),
            "CURRENT_QUARTER" => Ok(Self::CurrentQuarter),
            "NEXT_QUARTER" => Ok(Self::NextQuarter),
            "CURRENT_QUARTER_DELIVERING" => Ok(Self::CurrentQuarterDelivering),
            "NEXT_QUARTER_DELIVERING" => Ok(Self::NextQuarterDelivering),
            "PERPETUAL_DELIVERING" => Ok(Self::PerpetualDelivering),
            other => Err(format!("invalid BasisContractTypeEnum: {}", other).into()),
        }
    }
}

#[allow(non_camel_case_types)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum BasisPeriodEnum {
    #[serde(rename = "5m")]
    Period5m,
    #[serde(rename = "15m")]
    Period15m,
    #[serde(rename = "30m")]
    Period30m,
    #[serde(rename = "1h")]
    Period1h,
    #[serde(rename = "2h")]
    Period2h,
    #[serde(rename = "4h")]
    Period4h,
    #[serde(rename = "6h")]
    Period6h,
    #[serde(rename = "12h")]
    Period12h,
    #[serde(rename = "1d")]
    Period1d,
}

impl BasisPeriodEnum {
    #[must_use]
    pub fn as_str(&self) -> &'static str {
        match self {
            Self::Period5m => "5m",
            Self::Period15m => "15m",
            Self::Period30m => "30m",
            Self::Period1h => "1h",
            Self::Period2h => "2h",
            Self::Period4h => "4h",
            Self::Period6h => "6h",
            Self::Period12h => "12h",
            Self::Period1d => "1d",
        }
    }
}

impl std::str::FromStr for BasisPeriodEnum {
    type Err = Box<dyn std::error::Error + Send + Sync>;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "5m" => Ok(Self::Period5m),
            "15m" => Ok(Self::Period15m),
            "30m" => Ok(Self::Period30m),
            "1h" => Ok(Self::Period1h),
            "2h" => Ok(Self::Period2h),
            "4h" => Ok(Self::Period4h),
            "6h" => Ok(Self::Period6h),
            "12h" => Ok(Self::Period12h),
            "1d" => Ok(Self::Period1d),
            other => Err(format!("invalid BasisPeriodEnum: {}", other).into()),
        }
    }
}

#[allow(non_camel_case_types)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum ContinuousContractKlineCandlestickDataContractTypeEnum {
    #[serde(rename = "PERPETUAL")]
    Perpetual,
    #[serde(rename = "CURRENT_QUARTER")]
    CurrentQuarter,
    #[serde(rename = "NEXT_QUARTER")]
    NextQuarter,
    #[serde(rename = "CURRENT_QUARTER_DELIVERING")]
    CurrentQuarterDelivering,
    #[serde(rename = "NEXT_QUARTER_DELIVERING")]
    NextQuarterDelivering,
    #[serde(rename = "PERPETUAL_DELIVERING")]
    PerpetualDelivering,
}

impl ContinuousContractKlineCandlestickDataContractTypeEnum {
    #[must_use]
    pub fn as_str(&self) -> &'static str {
        match self {
            Self::Perpetual => "PERPETUAL",
            Self::CurrentQuarter => "CURRENT_QUARTER",
            Self::NextQuarter => "NEXT_QUARTER",
            Self::CurrentQuarterDelivering => "CURRENT_QUARTER_DELIVERING",
            Self::NextQuarterDelivering => "NEXT_QUARTER_DELIVERING",
            Self::PerpetualDelivering => "PERPETUAL_DELIVERING",
        }
    }
}

impl std::str::FromStr for ContinuousContractKlineCandlestickDataContractTypeEnum {
    type Err = Box<dyn std::error::Error + Send + Sync>;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "PERPETUAL" => Ok(Self::Perpetual),
            "CURRENT_QUARTER" => Ok(Self::CurrentQuarter),
            "NEXT_QUARTER" => Ok(Self::NextQuarter),
            "CURRENT_QUARTER_DELIVERING" => Ok(Self::CurrentQuarterDelivering),
            "NEXT_QUARTER_DELIVERING" => Ok(Self::NextQuarterDelivering),
            "PERPETUAL_DELIVERING" => Ok(Self::PerpetualDelivering),
            other => Err(format!(
                "invalid ContinuousContractKlineCandlestickDataContractTypeEnum: {}",
                other
            )
            .into()),
        }
    }
}

#[allow(non_camel_case_types)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum ContinuousContractKlineCandlestickDataIntervalEnum {
    #[serde(rename = "1m")]
    Interval1m,
    #[serde(rename = "3m")]
    Interval3m,
    #[serde(rename = "5m")]
    Interval5m,
    #[serde(rename = "15m")]
    Interval15m,
    #[serde(rename = "30m")]
    Interval30m,
    #[serde(rename = "1h")]
    Interval1h,
    #[serde(rename = "2h")]
    Interval2h,
    #[serde(rename = "4h")]
    Interval4h,
    #[serde(rename = "6h")]
    Interval6h,
    #[serde(rename = "8h")]
    Interval8h,
    #[serde(rename = "12h")]
    Interval12h,
    #[serde(rename = "1d")]
    Interval1d,
    #[serde(rename = "3d")]
    Interval3d,
    #[serde(rename = "1w")]
    Interval1w,
    #[serde(rename = "1M")]
    Interval1M,
}

impl ContinuousContractKlineCandlestickDataIntervalEnum {
    #[must_use]
    pub fn as_str(&self) -> &'static str {
        match self {
            Self::Interval1m => "1m",
            Self::Interval3m => "3m",
            Self::Interval5m => "5m",
            Self::Interval15m => "15m",
            Self::Interval30m => "30m",
            Self::Interval1h => "1h",
            Self::Interval2h => "2h",
            Self::Interval4h => "4h",
            Self::Interval6h => "6h",
            Self::Interval8h => "8h",
            Self::Interval12h => "12h",
            Self::Interval1d => "1d",
            Self::Interval3d => "3d",
            Self::Interval1w => "1w",
            Self::Interval1M => "1M",
        }
    }
}

impl std::str::FromStr for ContinuousContractKlineCandlestickDataIntervalEnum {
    type Err = Box<dyn std::error::Error + Send + Sync>;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "1m" => Ok(Self::Interval1m),
            "3m" => Ok(Self::Interval3m),
            "5m" => Ok(Self::Interval5m),
            "15m" => Ok(Self::Interval15m),
            "30m" => Ok(Self::Interval30m),
            "1h" => Ok(Self::Interval1h),
            "2h" => Ok(Self::Interval2h),
            "4h" => Ok(Self::Interval4h),
            "6h" => Ok(Self::Interval6h),
            "8h" => Ok(Self::Interval8h),
            "12h" => Ok(Self::Interval12h),
            "1d" => Ok(Self::Interval1d),
            "3d" => Ok(Self::Interval3d),
            "1w" => Ok(Self::Interval1w),
            "1M" => Ok(Self::Interval1M),
            other => Err(format!(
                "invalid ContinuousContractKlineCandlestickDataIntervalEnum: {}",
                other
            )
            .into()),
        }
    }
}

#[allow(non_camel_case_types)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum IndexPriceKlineCandlestickDataIntervalEnum {
    #[serde(rename = "1m")]
    Interval1m,
    #[serde(rename = "3m")]
    Interval3m,
    #[serde(rename = "5m")]
    Interval5m,
    #[serde(rename = "15m")]
    Interval15m,
    #[serde(rename = "30m")]
    Interval30m,
    #[serde(rename = "1h")]
    Interval1h,
    #[serde(rename = "2h")]
    Interval2h,
    #[serde(rename = "4h")]
    Interval4h,
    #[serde(rename = "6h")]
    Interval6h,
    #[serde(rename = "8h")]
    Interval8h,
    #[serde(rename = "12h")]
    Interval12h,
    #[serde(rename = "1d")]
    Interval1d,
    #[serde(rename = "3d")]
    Interval3d,
    #[serde(rename = "1w")]
    Interval1w,
    #[serde(rename = "1M")]
    Interval1M,
}

impl IndexPriceKlineCandlestickDataIntervalEnum {
    #[must_use]
    pub fn as_str(&self) -> &'static str {
        match self {
            Self::Interval1m => "1m",
            Self::Interval3m => "3m",
            Self::Interval5m => "5m",
            Self::Interval15m => "15m",
            Self::Interval30m => "30m",
            Self::Interval1h => "1h",
            Self::Interval2h => "2h",
            Self::Interval4h => "4h",
            Self::Interval6h => "6h",
            Self::Interval8h => "8h",
            Self::Interval12h => "12h",
            Self::Interval1d => "1d",
            Self::Interval3d => "3d",
            Self::Interval1w => "1w",
            Self::Interval1M => "1M",
        }
    }
}

impl std::str::FromStr for IndexPriceKlineCandlestickDataIntervalEnum {
    type Err = Box<dyn std::error::Error + Send + Sync>;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "1m" => Ok(Self::Interval1m),
            "3m" => Ok(Self::Interval3m),
            "5m" => Ok(Self::Interval5m),
            "15m" => Ok(Self::Interval15m),
            "30m" => Ok(Self::Interval30m),
            "1h" => Ok(Self::Interval1h),
            "2h" => Ok(Self::Interval2h),
            "4h" => Ok(Self::Interval4h),
            "6h" => Ok(Self::Interval6h),
            "8h" => Ok(Self::Interval8h),
            "12h" => Ok(Self::Interval12h),
            "1d" => Ok(Self::Interval1d),
            "3d" => Ok(Self::Interval3d),
            "1w" => Ok(Self::Interval1w),
            "1M" => Ok(Self::Interval1M),
            other => Err(format!(
                "invalid IndexPriceKlineCandlestickDataIntervalEnum: {}",
                other
            )
            .into()),
        }
    }
}

#[allow(non_camel_case_types)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum KlineCandlestickDataIntervalEnum {
    #[serde(rename = "1m")]
    Interval1m,
    #[serde(rename = "3m")]
    Interval3m,
    #[serde(rename = "5m")]
    Interval5m,
    #[serde(rename = "15m")]
    Interval15m,
    #[serde(rename = "30m")]
    Interval30m,
    #[serde(rename = "1h")]
    Interval1h,
    #[serde(rename = "2h")]
    Interval2h,
    #[serde(rename = "4h")]
    Interval4h,
    #[serde(rename = "6h")]
    Interval6h,
    #[serde(rename = "8h")]
    Interval8h,
    #[serde(rename = "12h")]
    Interval12h,
    #[serde(rename = "1d")]
    Interval1d,
    #[serde(rename = "3d")]
    Interval3d,
    #[serde(rename = "1w")]
    Interval1w,
    #[serde(rename = "1M")]
    Interval1M,
}

impl KlineCandlestickDataIntervalEnum {
    #[must_use]
    pub fn as_str(&self) -> &'static str {
        match self {
            Self::Interval1m => "1m",
            Self::Interval3m => "3m",
            Self::Interval5m => "5m",
            Self::Interval15m => "15m",
            Self::Interval30m => "30m",
            Self::Interval1h => "1h",
            Self::Interval2h => "2h",
            Self::Interval4h => "4h",
            Self::Interval6h => "6h",
            Self::Interval8h => "8h",
            Self::Interval12h => "12h",
            Self::Interval1d => "1d",
            Self::Interval3d => "3d",
            Self::Interval1w => "1w",
            Self::Interval1M => "1M",
        }
    }
}

impl std::str::FromStr for KlineCandlestickDataIntervalEnum {
    type Err = Box<dyn std::error::Error + Send + Sync>;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "1m" => Ok(Self::Interval1m),
            "3m" => Ok(Self::Interval3m),
            "5m" => Ok(Self::Interval5m),
            "15m" => Ok(Self::Interval15m),
            "30m" => Ok(Self::Interval30m),
            "1h" => Ok(Self::Interval1h),
            "2h" => Ok(Self::Interval2h),
            "4h" => Ok(Self::Interval4h),
            "6h" => Ok(Self::Interval6h),
            "8h" => Ok(Self::Interval8h),
            "12h" => Ok(Self::Interval12h),
            "1d" => Ok(Self::Interval1d),
            "3d" => Ok(Self::Interval3d),
            "1w" => Ok(Self::Interval1w),
            "1M" => Ok(Self::Interval1M),
            other => Err(format!("invalid KlineCandlestickDataIntervalEnum: {}", other).into()),
        }
    }
}

#[allow(non_camel_case_types)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum LongShortRatioPeriodEnum {
    #[serde(rename = "5m")]
    Period5m,
    #[serde(rename = "15m")]
    Period15m,
    #[serde(rename = "30m")]
    Period30m,
    #[serde(rename = "1h")]
    Period1h,
    #[serde(rename = "2h")]
    Period2h,
    #[serde(rename = "4h")]
    Period4h,
    #[serde(rename = "6h")]
    Period6h,
    #[serde(rename = "12h")]
    Period12h,
    #[serde(rename = "1d")]
    Period1d,
}

impl LongShortRatioPeriodEnum {
    #[must_use]
    pub fn as_str(&self) -> &'static str {
        match self {
            Self::Period5m => "5m",
            Self::Period15m => "15m",
            Self::Period30m => "30m",
            Self::Period1h => "1h",
            Self::Period2h => "2h",
            Self::Period4h => "4h",
            Self::Period6h => "6h",
            Self::Period12h => "12h",
            Self::Period1d => "1d",
        }
    }
}

impl std::str::FromStr for LongShortRatioPeriodEnum {
    type Err = Box<dyn std::error::Error + Send + Sync>;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "5m" => Ok(Self::Period5m),
            "15m" => Ok(Self::Period15m),
            "30m" => Ok(Self::Period30m),
            "1h" => Ok(Self::Period1h),
            "2h" => Ok(Self::Period2h),
            "4h" => Ok(Self::Period4h),
            "6h" => Ok(Self::Period6h),
            "12h" => Ok(Self::Period12h),
            "1d" => Ok(Self::Period1d),
            other => Err(format!("invalid LongShortRatioPeriodEnum: {}", other).into()),
        }
    }
}

#[allow(non_camel_case_types)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum MarkPriceKlineCandlestickDataIntervalEnum {
    #[serde(rename = "1m")]
    Interval1m,
    #[serde(rename = "3m")]
    Interval3m,
    #[serde(rename = "5m")]
    Interval5m,
    #[serde(rename = "15m")]
    Interval15m,
    #[serde(rename = "30m")]
    Interval30m,
    #[serde(rename = "1h")]
    Interval1h,
    #[serde(rename = "2h")]
    Interval2h,
    #[serde(rename = "4h")]
    Interval4h,
    #[serde(rename = "6h")]
    Interval6h,
    #[serde(rename = "8h")]
    Interval8h,
    #[serde(rename = "12h")]
    Interval12h,
    #[serde(rename = "1d")]
    Interval1d,
    #[serde(rename = "3d")]
    Interval3d,
    #[serde(rename = "1w")]
    Interval1w,
    #[serde(rename = "1M")]
    Interval1M,
}

impl MarkPriceKlineCandlestickDataIntervalEnum {
    #[must_use]
    pub fn as_str(&self) -> &'static str {
        match self {
            Self::Interval1m => "1m",
            Self::Interval3m => "3m",
            Self::Interval5m => "5m",
            Self::Interval15m => "15m",
            Self::Interval30m => "30m",
            Self::Interval1h => "1h",
            Self::Interval2h => "2h",
            Self::Interval4h => "4h",
            Self::Interval6h => "6h",
            Self::Interval8h => "8h",
            Self::Interval12h => "12h",
            Self::Interval1d => "1d",
            Self::Interval3d => "3d",
            Self::Interval1w => "1w",
            Self::Interval1M => "1M",
        }
    }
}

impl std::str::FromStr for MarkPriceKlineCandlestickDataIntervalEnum {
    type Err = Box<dyn std::error::Error + Send + Sync>;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "1m" => Ok(Self::Interval1m),
            "3m" => Ok(Self::Interval3m),
            "5m" => Ok(Self::Interval5m),
            "15m" => Ok(Self::Interval15m),
            "30m" => Ok(Self::Interval30m),
            "1h" => Ok(Self::Interval1h),
            "2h" => Ok(Self::Interval2h),
            "4h" => Ok(Self::Interval4h),
            "6h" => Ok(Self::Interval6h),
            "8h" => Ok(Self::Interval8h),
            "12h" => Ok(Self::Interval12h),
            "1d" => Ok(Self::Interval1d),
            "3d" => Ok(Self::Interval3d),
            "1w" => Ok(Self::Interval1w),
            "1M" => Ok(Self::Interval1M),
            other => Err(format!(
                "invalid MarkPriceKlineCandlestickDataIntervalEnum: {}",
                other
            )
            .into()),
        }
    }
}

#[allow(non_camel_case_types)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum OpenInterestStatisticsContractTypeEnum {
    #[serde(rename = "PERPETUAL")]
    Perpetual,
    #[serde(rename = "CURRENT_QUARTER")]
    CurrentQuarter,
    #[serde(rename = "NEXT_QUARTER")]
    NextQuarter,
    #[serde(rename = "CURRENT_QUARTER_DELIVERING")]
    CurrentQuarterDelivering,
    #[serde(rename = "NEXT_QUARTER_DELIVERING")]
    NextQuarterDelivering,
    #[serde(rename = "PERPETUAL_DELIVERING")]
    PerpetualDelivering,
}

impl OpenInterestStatisticsContractTypeEnum {
    #[must_use]
    pub fn as_str(&self) -> &'static str {
        match self {
            Self::Perpetual => "PERPETUAL",
            Self::CurrentQuarter => "CURRENT_QUARTER",
            Self::NextQuarter => "NEXT_QUARTER",
            Self::CurrentQuarterDelivering => "CURRENT_QUARTER_DELIVERING",
            Self::NextQuarterDelivering => "NEXT_QUARTER_DELIVERING",
            Self::PerpetualDelivering => "PERPETUAL_DELIVERING",
        }
    }
}

impl std::str::FromStr for OpenInterestStatisticsContractTypeEnum {
    type Err = Box<dyn std::error::Error + Send + Sync>;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "PERPETUAL" => Ok(Self::Perpetual),
            "CURRENT_QUARTER" => Ok(Self::CurrentQuarter),
            "NEXT_QUARTER" => Ok(Self::NextQuarter),
            "CURRENT_QUARTER_DELIVERING" => Ok(Self::CurrentQuarterDelivering),
            "NEXT_QUARTER_DELIVERING" => Ok(Self::NextQuarterDelivering),
            "PERPETUAL_DELIVERING" => Ok(Self::PerpetualDelivering),
            other => {
                Err(format!("invalid OpenInterestStatisticsContractTypeEnum: {}", other).into())
            }
        }
    }
}

#[allow(non_camel_case_types)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum OpenInterestStatisticsPeriodEnum {
    #[serde(rename = "5m")]
    Period5m,
    #[serde(rename = "15m")]
    Period15m,
    #[serde(rename = "30m")]
    Period30m,
    #[serde(rename = "1h")]
    Period1h,
    #[serde(rename = "2h")]
    Period2h,
    #[serde(rename = "4h")]
    Period4h,
    #[serde(rename = "6h")]
    Period6h,
    #[serde(rename = "12h")]
    Period12h,
    #[serde(rename = "1d")]
    Period1d,
}

impl OpenInterestStatisticsPeriodEnum {
    #[must_use]
    pub fn as_str(&self) -> &'static str {
        match self {
            Self::Period5m => "5m",
            Self::Period15m => "15m",
            Self::Period30m => "30m",
            Self::Period1h => "1h",
            Self::Period2h => "2h",
            Self::Period4h => "4h",
            Self::Period6h => "6h",
            Self::Period12h => "12h",
            Self::Period1d => "1d",
        }
    }
}

impl std::str::FromStr for OpenInterestStatisticsPeriodEnum {
    type Err = Box<dyn std::error::Error + Send + Sync>;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "5m" => Ok(Self::Period5m),
            "15m" => Ok(Self::Period15m),
            "30m" => Ok(Self::Period30m),
            "1h" => Ok(Self::Period1h),
            "2h" => Ok(Self::Period2h),
            "4h" => Ok(Self::Period4h),
            "6h" => Ok(Self::Period6h),
            "12h" => Ok(Self::Period12h),
            "1d" => Ok(Self::Period1d),
            other => Err(format!("invalid OpenInterestStatisticsPeriodEnum: {}", other).into()),
        }
    }
}

#[allow(non_camel_case_types)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum PremiumIndexKlineDataIntervalEnum {
    #[serde(rename = "1m")]
    Interval1m,
    #[serde(rename = "3m")]
    Interval3m,
    #[serde(rename = "5m")]
    Interval5m,
    #[serde(rename = "15m")]
    Interval15m,
    #[serde(rename = "30m")]
    Interval30m,
    #[serde(rename = "1h")]
    Interval1h,
    #[serde(rename = "2h")]
    Interval2h,
    #[serde(rename = "4h")]
    Interval4h,
    #[serde(rename = "6h")]
    Interval6h,
    #[serde(rename = "8h")]
    Interval8h,
    #[serde(rename = "12h")]
    Interval12h,
    #[serde(rename = "1d")]
    Interval1d,
    #[serde(rename = "3d")]
    Interval3d,
    #[serde(rename = "1w")]
    Interval1w,
    #[serde(rename = "1M")]
    Interval1M,
}

impl PremiumIndexKlineDataIntervalEnum {
    #[must_use]
    pub fn as_str(&self) -> &'static str {
        match self {
            Self::Interval1m => "1m",
            Self::Interval3m => "3m",
            Self::Interval5m => "5m",
            Self::Interval15m => "15m",
            Self::Interval30m => "30m",
            Self::Interval1h => "1h",
            Self::Interval2h => "2h",
            Self::Interval4h => "4h",
            Self::Interval6h => "6h",
            Self::Interval8h => "8h",
            Self::Interval12h => "12h",
            Self::Interval1d => "1d",
            Self::Interval3d => "3d",
            Self::Interval1w => "1w",
            Self::Interval1M => "1M",
        }
    }
}

impl std::str::FromStr for PremiumIndexKlineDataIntervalEnum {
    type Err = Box<dyn std::error::Error + Send + Sync>;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "1m" => Ok(Self::Interval1m),
            "3m" => Ok(Self::Interval3m),
            "5m" => Ok(Self::Interval5m),
            "15m" => Ok(Self::Interval15m),
            "30m" => Ok(Self::Interval30m),
            "1h" => Ok(Self::Interval1h),
            "2h" => Ok(Self::Interval2h),
            "4h" => Ok(Self::Interval4h),
            "6h" => Ok(Self::Interval6h),
            "8h" => Ok(Self::Interval8h),
            "12h" => Ok(Self::Interval12h),
            "1d" => Ok(Self::Interval1d),
            "3d" => Ok(Self::Interval3d),
            "1w" => Ok(Self::Interval1w),
            "1M" => Ok(Self::Interval1M),
            other => Err(format!("invalid PremiumIndexKlineDataIntervalEnum: {}", other).into()),
        }
    }
}

#[allow(non_camel_case_types)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum TakerBuySellVolumeContractTypeEnum {
    #[serde(rename = "PERPETUAL")]
    Perpetual,
    #[serde(rename = "CURRENT_QUARTER")]
    CurrentQuarter,
    #[serde(rename = "NEXT_QUARTER")]
    NextQuarter,
    #[serde(rename = "CURRENT_QUARTER_DELIVERING")]
    CurrentQuarterDelivering,
    #[serde(rename = "NEXT_QUARTER_DELIVERING")]
    NextQuarterDelivering,
    #[serde(rename = "PERPETUAL_DELIVERING")]
    PerpetualDelivering,
}

impl TakerBuySellVolumeContractTypeEnum {
    #[must_use]
    pub fn as_str(&self) -> &'static str {
        match self {
            Self::Perpetual => "PERPETUAL",
            Self::CurrentQuarter => "CURRENT_QUARTER",
            Self::NextQuarter => "NEXT_QUARTER",
            Self::CurrentQuarterDelivering => "CURRENT_QUARTER_DELIVERING",
            Self::NextQuarterDelivering => "NEXT_QUARTER_DELIVERING",
            Self::PerpetualDelivering => "PERPETUAL_DELIVERING",
        }
    }
}

impl std::str::FromStr for TakerBuySellVolumeContractTypeEnum {
    type Err = Box<dyn std::error::Error + Send + Sync>;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "PERPETUAL" => Ok(Self::Perpetual),
            "CURRENT_QUARTER" => Ok(Self::CurrentQuarter),
            "NEXT_QUARTER" => Ok(Self::NextQuarter),
            "CURRENT_QUARTER_DELIVERING" => Ok(Self::CurrentQuarterDelivering),
            "NEXT_QUARTER_DELIVERING" => Ok(Self::NextQuarterDelivering),
            "PERPETUAL_DELIVERING" => Ok(Self::PerpetualDelivering),
            other => Err(format!("invalid TakerBuySellVolumeContractTypeEnum: {}", other).into()),
        }
    }
}

#[allow(non_camel_case_types)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum TakerBuySellVolumePeriodEnum {
    #[serde(rename = "5m")]
    Period5m,
    #[serde(rename = "15m")]
    Period15m,
    #[serde(rename = "30m")]
    Period30m,
    #[serde(rename = "1h")]
    Period1h,
    #[serde(rename = "2h")]
    Period2h,
    #[serde(rename = "4h")]
    Period4h,
    #[serde(rename = "6h")]
    Period6h,
    #[serde(rename = "12h")]
    Period12h,
    #[serde(rename = "1d")]
    Period1d,
}

impl TakerBuySellVolumePeriodEnum {
    #[must_use]
    pub fn as_str(&self) -> &'static str {
        match self {
            Self::Period5m => "5m",
            Self::Period15m => "15m",
            Self::Period30m => "30m",
            Self::Period1h => "1h",
            Self::Period2h => "2h",
            Self::Period4h => "4h",
            Self::Period6h => "6h",
            Self::Period12h => "12h",
            Self::Period1d => "1d",
        }
    }
}

impl std::str::FromStr for TakerBuySellVolumePeriodEnum {
    type Err = Box<dyn std::error::Error + Send + Sync>;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "5m" => Ok(Self::Period5m),
            "15m" => Ok(Self::Period15m),
            "30m" => Ok(Self::Period30m),
            "1h" => Ok(Self::Period1h),
            "2h" => Ok(Self::Period2h),
            "4h" => Ok(Self::Period4h),
            "6h" => Ok(Self::Period6h),
            "12h" => Ok(Self::Period12h),
            "1d" => Ok(Self::Period1d),
            other => Err(format!("invalid TakerBuySellVolumePeriodEnum: {}", other).into()),
        }
    }
}

#[allow(non_camel_case_types)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum TopTraderLongShortRatioAccountsPeriodEnum {
    #[serde(rename = "5m")]
    Period5m,
    #[serde(rename = "15m")]
    Period15m,
    #[serde(rename = "30m")]
    Period30m,
    #[serde(rename = "1h")]
    Period1h,
    #[serde(rename = "2h")]
    Period2h,
    #[serde(rename = "4h")]
    Period4h,
    #[serde(rename = "6h")]
    Period6h,
    #[serde(rename = "12h")]
    Period12h,
    #[serde(rename = "1d")]
    Period1d,
}

impl TopTraderLongShortRatioAccountsPeriodEnum {
    #[must_use]
    pub fn as_str(&self) -> &'static str {
        match self {
            Self::Period5m => "5m",
            Self::Period15m => "15m",
            Self::Period30m => "30m",
            Self::Period1h => "1h",
            Self::Period2h => "2h",
            Self::Period4h => "4h",
            Self::Period6h => "6h",
            Self::Period12h => "12h",
            Self::Period1d => "1d",
        }
    }
}

impl std::str::FromStr for TopTraderLongShortRatioAccountsPeriodEnum {
    type Err = Box<dyn std::error::Error + Send + Sync>;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "5m" => Ok(Self::Period5m),
            "15m" => Ok(Self::Period15m),
            "30m" => Ok(Self::Period30m),
            "1h" => Ok(Self::Period1h),
            "2h" => Ok(Self::Period2h),
            "4h" => Ok(Self::Period4h),
            "6h" => Ok(Self::Period6h),
            "12h" => Ok(Self::Period12h),
            "1d" => Ok(Self::Period1d),
            other => Err(format!(
                "invalid TopTraderLongShortRatioAccountsPeriodEnum: {}",
                other
            )
            .into()),
        }
    }
}

#[allow(non_camel_case_types)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum TopTraderLongShortRatioPositionsPeriodEnum {
    #[serde(rename = "5m")]
    Period5m,
    #[serde(rename = "15m")]
    Period15m,
    #[serde(rename = "30m")]
    Period30m,
    #[serde(rename = "1h")]
    Period1h,
    #[serde(rename = "2h")]
    Period2h,
    #[serde(rename = "4h")]
    Period4h,
    #[serde(rename = "6h")]
    Period6h,
    #[serde(rename = "12h")]
    Period12h,
    #[serde(rename = "1d")]
    Period1d,
}

impl TopTraderLongShortRatioPositionsPeriodEnum {
    #[must_use]
    pub fn as_str(&self) -> &'static str {
        match self {
            Self::Period5m => "5m",
            Self::Period15m => "15m",
            Self::Period30m => "30m",
            Self::Period1h => "1h",
            Self::Period2h => "2h",
            Self::Period4h => "4h",
            Self::Period6h => "6h",
            Self::Period12h => "12h",
            Self::Period1d => "1d",
        }
    }
}

impl std::str::FromStr for TopTraderLongShortRatioPositionsPeriodEnum {
    type Err = Box<dyn std::error::Error + Send + Sync>;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "5m" => Ok(Self::Period5m),
            "15m" => Ok(Self::Period15m),
            "30m" => Ok(Self::Period30m),
            "1h" => Ok(Self::Period1h),
            "2h" => Ok(Self::Period2h),
            "4h" => Ok(Self::Period4h),
            "6h" => Ok(Self::Period6h),
            "12h" => Ok(Self::Period12h),
            "1d" => Ok(Self::Period1d),
            other => Err(format!(
                "invalid TopTraderLongShortRatioPositionsPeriodEnum: {}",
                other
            )
            .into()),
        }
    }
}

/// Request parameters for the [`basis`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`basis`](#method.basis).
#[derive(Clone, Debug, Builder)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct BasisParams {
    /// BTCUSD
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub pair: String,
    /// ALL, `CURRENT_QUARTER`, `NEXT_QUARTER`, PERPETUAL
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub contract_type: BasisContractTypeEnum,
    /// "5m","15m","30m","1h","2h","4h","6h","12h","1d"
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub period: BasisPeriodEnum,
    /// Default 100; max 1000
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub limit: Option<i64>,
    ///
    /// The `start_time` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub start_time: Option<i64>,
    ///
    /// The `end_time` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub end_time: Option<i64>,
}

impl BasisParams {
    /// Create a builder for [`basis`].
    ///
    /// Required parameters:
    ///
    /// * `pair` — BTCUSD
    /// * `contract_type` — ALL, `CURRENT_QUARTER`, `NEXT_QUARTER`, PERPETUAL
    /// * `period` — \"5m\",\"15m\",\"30m\",\"1h\",\"2h\",\"4h\",\"6h\",\"12h\",\"1d\"
    ///
    #[must_use]
    pub fn builder(
        pair: String,
        contract_type: BasisContractTypeEnum,
        period: BasisPeriodEnum,
    ) -> BasisParamsBuilder {
        BasisParamsBuilder::default()
            .pair(pair)
            .contract_type(contract_type)
            .period(period)
    }
}
/// Request parameters for the [`compressed_aggregate_trades_list`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`compressed_aggregate_trades_list`](#method.compressed_aggregate_trades_list).
#[derive(Clone, Debug, Builder)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct CompressedAggregateTradesListParams {
    ///
    /// The `symbol` parameter.
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub symbol: String,
    /// ID to get aggregate trades from INCLUSIVE.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub from_id: Option<i64>,
    ///
    /// The `start_time` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub start_time: Option<i64>,
    ///
    /// The `end_time` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub end_time: Option<i64>,
    /// Default 100; max 1000
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub limit: Option<i64>,
}

impl CompressedAggregateTradesListParams {
    /// Create a builder for [`compressed_aggregate_trades_list`].
    ///
    /// Required parameters:
    ///
    /// * `symbol` — String
    ///
    #[must_use]
    pub fn builder(symbol: String) -> CompressedAggregateTradesListParamsBuilder {
        CompressedAggregateTradesListParamsBuilder::default().symbol(symbol)
    }
}
/// Request parameters for the [`continuous_contract_kline_candlestick_data`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`continuous_contract_kline_candlestick_data`](#method.continuous_contract_kline_candlestick_data).
#[derive(Clone, Debug, Builder)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct ContinuousContractKlineCandlestickDataParams {
    /// BTCUSD
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub pair: String,
    /// ALL, `CURRENT_QUARTER`, `NEXT_QUARTER`, PERPETUAL
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub contract_type: ContinuousContractKlineCandlestickDataContractTypeEnum,
    ///
    /// The `interval` parameter.
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub interval: ContinuousContractKlineCandlestickDataIntervalEnum,
    ///
    /// The `start_time` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub start_time: Option<i64>,
    ///
    /// The `end_time` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub end_time: Option<i64>,
    /// Default 100; max 1000
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub limit: Option<i64>,
}

impl ContinuousContractKlineCandlestickDataParams {
    /// Create a builder for [`continuous_contract_kline_candlestick_data`].
    ///
    /// Required parameters:
    ///
    /// * `pair` — BTCUSD
    /// * `contract_type` — ALL, `CURRENT_QUARTER`, `NEXT_QUARTER`, PERPETUAL
    /// * `interval` — String
    ///
    #[must_use]
    pub fn builder(
        pair: String,
        contract_type: ContinuousContractKlineCandlestickDataContractTypeEnum,
        interval: ContinuousContractKlineCandlestickDataIntervalEnum,
    ) -> ContinuousContractKlineCandlestickDataParamsBuilder {
        ContinuousContractKlineCandlestickDataParamsBuilder::default()
            .pair(pair)
            .contract_type(contract_type)
            .interval(interval)
    }
}
/// Request parameters for the [`get_funding_rate_history_of_perpetual_futures`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`get_funding_rate_history_of_perpetual_futures`](#method.get_funding_rate_history_of_perpetual_futures).
#[derive(Clone, Debug, Builder)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct GetFundingRateHistoryOfPerpetualFuturesParams {
    ///
    /// The `symbol` parameter.
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub symbol: String,
    ///
    /// The `start_time` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub start_time: Option<i64>,
    ///
    /// The `end_time` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub end_time: Option<i64>,
    /// Default 100; max 1000
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub limit: Option<i64>,
}

impl GetFundingRateHistoryOfPerpetualFuturesParams {
    /// Create a builder for [`get_funding_rate_history_of_perpetual_futures`].
    ///
    /// Required parameters:
    ///
    /// * `symbol` — String
    ///
    #[must_use]
    pub fn builder(symbol: String) -> GetFundingRateHistoryOfPerpetualFuturesParamsBuilder {
        GetFundingRateHistoryOfPerpetualFuturesParamsBuilder::default().symbol(symbol)
    }
}
/// Request parameters for the [`index_price_and_mark_price`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`index_price_and_mark_price`](#method.index_price_and_mark_price).
#[derive(Clone, Debug, Builder, Default)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct IndexPriceAndMarkPriceParams {
    ///
    /// The `symbol` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub symbol: Option<String>,
    ///
    /// The `pair` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub pair: Option<String>,
}

impl IndexPriceAndMarkPriceParams {
    /// Create a builder for [`index_price_and_mark_price`].
    ///
    #[must_use]
    pub fn builder() -> IndexPriceAndMarkPriceParamsBuilder {
        IndexPriceAndMarkPriceParamsBuilder::default()
    }
}
/// Request parameters for the [`index_price_kline_candlestick_data`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`index_price_kline_candlestick_data`](#method.index_price_kline_candlestick_data).
#[derive(Clone, Debug, Builder)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct IndexPriceKlineCandlestickDataParams {
    /// BTCUSD
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub pair: String,
    ///
    /// The `interval` parameter.
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub interval: IndexPriceKlineCandlestickDataIntervalEnum,
    ///
    /// The `start_time` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub start_time: Option<i64>,
    ///
    /// The `end_time` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub end_time: Option<i64>,
    /// Default 100; max 1000
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub limit: Option<i64>,
}

impl IndexPriceKlineCandlestickDataParams {
    /// Create a builder for [`index_price_kline_candlestick_data`].
    ///
    /// Required parameters:
    ///
    /// * `pair` — BTCUSD
    /// * `interval` — String
    ///
    #[must_use]
    pub fn builder(
        pair: String,
        interval: IndexPriceKlineCandlestickDataIntervalEnum,
    ) -> IndexPriceKlineCandlestickDataParamsBuilder {
        IndexPriceKlineCandlestickDataParamsBuilder::default()
            .pair(pair)
            .interval(interval)
    }
}
/// Request parameters for the [`kline_candlestick_data`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`kline_candlestick_data`](#method.kline_candlestick_data).
#[derive(Clone, Debug, Builder)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct KlineCandlestickDataParams {
    ///
    /// The `symbol` parameter.
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub symbol: String,
    ///
    /// The `interval` parameter.
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub interval: KlineCandlestickDataIntervalEnum,
    ///
    /// The `start_time` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub start_time: Option<i64>,
    ///
    /// The `end_time` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub end_time: Option<i64>,
    /// Default 100; max 1000
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub limit: Option<i64>,
}

impl KlineCandlestickDataParams {
    /// Create a builder for [`kline_candlestick_data`].
    ///
    /// Required parameters:
    ///
    /// * `symbol` — String
    /// * `interval` — String
    ///
    #[must_use]
    pub fn builder(
        symbol: String,
        interval: KlineCandlestickDataIntervalEnum,
    ) -> KlineCandlestickDataParamsBuilder {
        KlineCandlestickDataParamsBuilder::default()
            .symbol(symbol)
            .interval(interval)
    }
}
/// Request parameters for the [`long_short_ratio`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`long_short_ratio`](#method.long_short_ratio).
#[derive(Clone, Debug, Builder)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct LongShortRatioParams {
    /// BTCUSD
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub pair: String,
    /// "5m","15m","30m","1h","2h","4h","6h","12h","1d"
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub period: LongShortRatioPeriodEnum,
    /// Default 100; max 1000
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub limit: Option<i64>,
    ///
    /// The `start_time` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub start_time: Option<i64>,
    ///
    /// The `end_time` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub end_time: Option<i64>,
}

impl LongShortRatioParams {
    /// Create a builder for [`long_short_ratio`].
    ///
    /// Required parameters:
    ///
    /// * `pair` — BTCUSD
    /// * `period` — \"5m\",\"15m\",\"30m\",\"1h\",\"2h\",\"4h\",\"6h\",\"12h\",\"1d\"
    ///
    #[must_use]
    pub fn builder(pair: String, period: LongShortRatioPeriodEnum) -> LongShortRatioParamsBuilder {
        LongShortRatioParamsBuilder::default()
            .pair(pair)
            .period(period)
    }
}
/// Request parameters for the [`mark_price_kline_candlestick_data`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`mark_price_kline_candlestick_data`](#method.mark_price_kline_candlestick_data).
#[derive(Clone, Debug, Builder)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct MarkPriceKlineCandlestickDataParams {
    ///
    /// The `symbol` parameter.
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub symbol: String,
    ///
    /// The `interval` parameter.
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub interval: MarkPriceKlineCandlestickDataIntervalEnum,
    ///
    /// The `start_time` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub start_time: Option<i64>,
    ///
    /// The `end_time` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub end_time: Option<i64>,
    /// Default 100; max 1000
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub limit: Option<i64>,
}

impl MarkPriceKlineCandlestickDataParams {
    /// Create a builder for [`mark_price_kline_candlestick_data`].
    ///
    /// Required parameters:
    ///
    /// * `symbol` — String
    /// * `interval` — String
    ///
    #[must_use]
    pub fn builder(
        symbol: String,
        interval: MarkPriceKlineCandlestickDataIntervalEnum,
    ) -> MarkPriceKlineCandlestickDataParamsBuilder {
        MarkPriceKlineCandlestickDataParamsBuilder::default()
            .symbol(symbol)
            .interval(interval)
    }
}
/// Request parameters for the [`old_trades_lookup`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`old_trades_lookup`](#method.old_trades_lookup).
#[derive(Clone, Debug, Builder)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct OldTradesLookupParams {
    ///
    /// The `symbol` parameter.
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub symbol: String,
    /// Default 100; max 1000
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub limit: Option<i64>,
    /// ID to get aggregate trades from INCLUSIVE.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub from_id: Option<i64>,
}

impl OldTradesLookupParams {
    /// Create a builder for [`old_trades_lookup`].
    ///
    /// Required parameters:
    ///
    /// * `symbol` — String
    ///
    #[must_use]
    pub fn builder(symbol: String) -> OldTradesLookupParamsBuilder {
        OldTradesLookupParamsBuilder::default().symbol(symbol)
    }
}
/// Request parameters for the [`open_interest`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`open_interest`](#method.open_interest).
#[derive(Clone, Debug, Builder)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct OpenInterestParams {
    ///
    /// The `symbol` parameter.
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub symbol: String,
}

impl OpenInterestParams {
    /// Create a builder for [`open_interest`].
    ///
    /// Required parameters:
    ///
    /// * `symbol` — String
    ///
    #[must_use]
    pub fn builder(symbol: String) -> OpenInterestParamsBuilder {
        OpenInterestParamsBuilder::default().symbol(symbol)
    }
}
/// Request parameters for the [`open_interest_statistics`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`open_interest_statistics`](#method.open_interest_statistics).
#[derive(Clone, Debug, Builder)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct OpenInterestStatisticsParams {
    /// BTCUSD
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub pair: String,
    /// ALL, `CURRENT_QUARTER`, `NEXT_QUARTER`, PERPETUAL
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub contract_type: OpenInterestStatisticsContractTypeEnum,
    /// "5m","15m","30m","1h","2h","4h","6h","12h","1d"
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub period: OpenInterestStatisticsPeriodEnum,
    /// Default 100; max 1000
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub limit: Option<i64>,
    ///
    /// The `start_time` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub start_time: Option<i64>,
    ///
    /// The `end_time` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub end_time: Option<i64>,
}

impl OpenInterestStatisticsParams {
    /// Create a builder for [`open_interest_statistics`].
    ///
    /// Required parameters:
    ///
    /// * `pair` — BTCUSD
    /// * `contract_type` — ALL, `CURRENT_QUARTER`, `NEXT_QUARTER`, PERPETUAL
    /// * `period` — \"5m\",\"15m\",\"30m\",\"1h\",\"2h\",\"4h\",\"6h\",\"12h\",\"1d\"
    ///
    #[must_use]
    pub fn builder(
        pair: String,
        contract_type: OpenInterestStatisticsContractTypeEnum,
        period: OpenInterestStatisticsPeriodEnum,
    ) -> OpenInterestStatisticsParamsBuilder {
        OpenInterestStatisticsParamsBuilder::default()
            .pair(pair)
            .contract_type(contract_type)
            .period(period)
    }
}
/// Request parameters for the [`order_book`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`order_book`](#method.order_book).
#[derive(Clone, Debug, Builder)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct OrderBookParams {
    ///
    /// The `symbol` parameter.
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub symbol: String,
    /// Default 100; max 1000
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub limit: Option<i64>,
}

impl OrderBookParams {
    /// Create a builder for [`order_book`].
    ///
    /// Required parameters:
    ///
    /// * `symbol` — String
    ///
    #[must_use]
    pub fn builder(symbol: String) -> OrderBookParamsBuilder {
        OrderBookParamsBuilder::default().symbol(symbol)
    }
}
/// Request parameters for the [`premium_index_kline_data`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`premium_index_kline_data`](#method.premium_index_kline_data).
#[derive(Clone, Debug, Builder)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct PremiumIndexKlineDataParams {
    ///
    /// The `symbol` parameter.
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub symbol: String,
    ///
    /// The `interval` parameter.
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub interval: PremiumIndexKlineDataIntervalEnum,
    ///
    /// The `start_time` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub start_time: Option<i64>,
    ///
    /// The `end_time` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub end_time: Option<i64>,
    /// Default 100; max 1000
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub limit: Option<i64>,
}

impl PremiumIndexKlineDataParams {
    /// Create a builder for [`premium_index_kline_data`].
    ///
    /// Required parameters:
    ///
    /// * `symbol` — String
    /// * `interval` — String
    ///
    #[must_use]
    pub fn builder(
        symbol: String,
        interval: PremiumIndexKlineDataIntervalEnum,
    ) -> PremiumIndexKlineDataParamsBuilder {
        PremiumIndexKlineDataParamsBuilder::default()
            .symbol(symbol)
            .interval(interval)
    }
}
/// Request parameters for the [`query_index_price_constituents`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`query_index_price_constituents`](#method.query_index_price_constituents).
#[derive(Clone, Debug, Builder)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct QueryIndexPriceConstituentsParams {
    ///
    /// The `symbol` parameter.
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub symbol: String,
}

impl QueryIndexPriceConstituentsParams {
    /// Create a builder for [`query_index_price_constituents`].
    ///
    /// Required parameters:
    ///
    /// * `symbol` — String
    ///
    #[must_use]
    pub fn builder(symbol: String) -> QueryIndexPriceConstituentsParamsBuilder {
        QueryIndexPriceConstituentsParamsBuilder::default().symbol(symbol)
    }
}
/// Request parameters for the [`recent_trades_list`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`recent_trades_list`](#method.recent_trades_list).
#[derive(Clone, Debug, Builder)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct RecentTradesListParams {
    ///
    /// The `symbol` parameter.
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub symbol: String,
    /// Default 100; max 1000
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub limit: Option<i64>,
}

impl RecentTradesListParams {
    /// Create a builder for [`recent_trades_list`].
    ///
    /// Required parameters:
    ///
    /// * `symbol` — String
    ///
    #[must_use]
    pub fn builder(symbol: String) -> RecentTradesListParamsBuilder {
        RecentTradesListParamsBuilder::default().symbol(symbol)
    }
}
/// Request parameters for the [`symbol_order_book_ticker`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`symbol_order_book_ticker`](#method.symbol_order_book_ticker).
#[derive(Clone, Debug, Builder, Default)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct SymbolOrderBookTickerParams {
    ///
    /// The `symbol` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub symbol: Option<String>,
    ///
    /// The `pair` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub pair: Option<String>,
}

impl SymbolOrderBookTickerParams {
    /// Create a builder for [`symbol_order_book_ticker`].
    ///
    #[must_use]
    pub fn builder() -> SymbolOrderBookTickerParamsBuilder {
        SymbolOrderBookTickerParamsBuilder::default()
    }
}
/// Request parameters for the [`symbol_price_ticker`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`symbol_price_ticker`](#method.symbol_price_ticker).
#[derive(Clone, Debug, Builder, Default)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct SymbolPriceTickerParams {
    ///
    /// The `symbol` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub symbol: Option<String>,
    ///
    /// The `pair` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub pair: Option<String>,
}

impl SymbolPriceTickerParams {
    /// Create a builder for [`symbol_price_ticker`].
    ///
    #[must_use]
    pub fn builder() -> SymbolPriceTickerParamsBuilder {
        SymbolPriceTickerParamsBuilder::default()
    }
}
/// Request parameters for the [`taker_buy_sell_volume`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`taker_buy_sell_volume`](#method.taker_buy_sell_volume).
#[derive(Clone, Debug, Builder)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct TakerBuySellVolumeParams {
    /// BTCUSD
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub pair: String,
    /// ALL, `CURRENT_QUARTER`, `NEXT_QUARTER`, PERPETUAL
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub contract_type: TakerBuySellVolumeContractTypeEnum,
    /// "5m","15m","30m","1h","2h","4h","6h","12h","1d"
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub period: TakerBuySellVolumePeriodEnum,
    /// Default 100; max 1000
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub limit: Option<i64>,
    ///
    /// The `start_time` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub start_time: Option<i64>,
    ///
    /// The `end_time` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub end_time: Option<i64>,
}

impl TakerBuySellVolumeParams {
    /// Create a builder for [`taker_buy_sell_volume`].
    ///
    /// Required parameters:
    ///
    /// * `pair` — BTCUSD
    /// * `contract_type` — ALL, `CURRENT_QUARTER`, `NEXT_QUARTER`, PERPETUAL
    /// * `period` — \"5m\",\"15m\",\"30m\",\"1h\",\"2h\",\"4h\",\"6h\",\"12h\",\"1d\"
    ///
    #[must_use]
    pub fn builder(
        pair: String,
        contract_type: TakerBuySellVolumeContractTypeEnum,
        period: TakerBuySellVolumePeriodEnum,
    ) -> TakerBuySellVolumeParamsBuilder {
        TakerBuySellVolumeParamsBuilder::default()
            .pair(pair)
            .contract_type(contract_type)
            .period(period)
    }
}
/// Request parameters for the [`ticker24hr_price_change_statistics`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`ticker24hr_price_change_statistics`](#method.ticker24hr_price_change_statistics).
#[derive(Clone, Debug, Builder, Default)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct Ticker24hrPriceChangeStatisticsParams {
    ///
    /// The `symbol` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub symbol: Option<String>,
    ///
    /// The `pair` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub pair: Option<String>,
}

impl Ticker24hrPriceChangeStatisticsParams {
    /// Create a builder for [`ticker24hr_price_change_statistics`].
    ///
    #[must_use]
    pub fn builder() -> Ticker24hrPriceChangeStatisticsParamsBuilder {
        Ticker24hrPriceChangeStatisticsParamsBuilder::default()
    }
}
/// Request parameters for the [`top_trader_long_short_ratio_accounts`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`top_trader_long_short_ratio_accounts`](#method.top_trader_long_short_ratio_accounts).
#[derive(Clone, Debug, Builder)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct TopTraderLongShortRatioAccountsParams {
    ///
    /// The `symbol` parameter.
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub symbol: String,
    /// "5m","15m","30m","1h","2h","4h","6h","12h","1d"
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub period: TopTraderLongShortRatioAccountsPeriodEnum,
    /// Default 100; max 1000
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub limit: Option<i64>,
    ///
    /// The `start_time` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub start_time: Option<i64>,
    ///
    /// The `end_time` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub end_time: Option<i64>,
}

impl TopTraderLongShortRatioAccountsParams {
    /// Create a builder for [`top_trader_long_short_ratio_accounts`].
    ///
    /// Required parameters:
    ///
    /// * `symbol` — String
    /// * `period` — \"5m\",\"15m\",\"30m\",\"1h\",\"2h\",\"4h\",\"6h\",\"12h\",\"1d\"
    ///
    #[must_use]
    pub fn builder(
        symbol: String,
        period: TopTraderLongShortRatioAccountsPeriodEnum,
    ) -> TopTraderLongShortRatioAccountsParamsBuilder {
        TopTraderLongShortRatioAccountsParamsBuilder::default()
            .symbol(symbol)
            .period(period)
    }
}
/// Request parameters for the [`top_trader_long_short_ratio_positions`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`top_trader_long_short_ratio_positions`](#method.top_trader_long_short_ratio_positions).
#[derive(Clone, Debug, Builder)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct TopTraderLongShortRatioPositionsParams {
    /// BTCUSD
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub pair: String,
    /// "5m","15m","30m","1h","2h","4h","6h","12h","1d"
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub period: TopTraderLongShortRatioPositionsPeriodEnum,
    /// Default 100; max 1000
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub limit: Option<i64>,
    ///
    /// The `start_time` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub start_time: Option<i64>,
    ///
    /// The `end_time` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub end_time: Option<i64>,
}

impl TopTraderLongShortRatioPositionsParams {
    /// Create a builder for [`top_trader_long_short_ratio_positions`].
    ///
    /// Required parameters:
    ///
    /// * `pair` — BTCUSD
    /// * `period` — \"5m\",\"15m\",\"30m\",\"1h\",\"2h\",\"4h\",\"6h\",\"12h\",\"1d\"
    ///
    #[must_use]
    pub fn builder(
        pair: String,
        period: TopTraderLongShortRatioPositionsPeriodEnum,
    ) -> TopTraderLongShortRatioPositionsParamsBuilder {
        TopTraderLongShortRatioPositionsParamsBuilder::default()
            .pair(pair)
            .period(period)
    }
}

#[async_trait]
impl MarketDataApi for MarketDataApiClient {
    async fn basis(
        &self,
        params: BasisParams,
    ) -> anyhow::Result<RestApiResponse<Vec<models::BasisResponseInner>>> {
        let BasisParams {
            pair,
            contract_type,
            period,
            limit,
            start_time,
            end_time,
        } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        query_params.insert("pair".to_string(), json!(pair));

        query_params.insert("contractType".to_string(), json!(contract_type));

        query_params.insert("period".to_string(), json!(period));

        if let Some(rw) = limit {
            query_params.insert("limit".to_string(), json!(rw));
        }

        if let Some(rw) = start_time {
            query_params.insert("startTime".to_string(), json!(rw));
        }

        if let Some(rw) = end_time {
            query_params.insert("endTime".to_string(), json!(rw));
        }

        send_request::<Vec<models::BasisResponseInner>>(
            &self.configuration,
            "/futures/data/basis",
            reqwest::Method::GET,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            false,
        )
        .await
    }

    async fn check_server_time(
        &self,
    ) -> anyhow::Result<RestApiResponse<models::CheckServerTimeResponse>> {
        let query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        send_request::<models::CheckServerTimeResponse>(
            &self.configuration,
            "/dapi/v1/time",
            reqwest::Method::GET,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            false,
        )
        .await
    }

    async fn compressed_aggregate_trades_list(
        &self,
        params: CompressedAggregateTradesListParams,
    ) -> anyhow::Result<RestApiResponse<Vec<models::CompressedAggregateTradesListResponseInner>>>
    {
        let CompressedAggregateTradesListParams {
            symbol,
            from_id,
            start_time,
            end_time,
            limit,
        } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        query_params.insert("symbol".to_string(), json!(symbol));

        if let Some(rw) = from_id {
            query_params.insert("fromId".to_string(), json!(rw));
        }

        if let Some(rw) = start_time {
            query_params.insert("startTime".to_string(), json!(rw));
        }

        if let Some(rw) = end_time {
            query_params.insert("endTime".to_string(), json!(rw));
        }

        if let Some(rw) = limit {
            query_params.insert("limit".to_string(), json!(rw));
        }

        send_request::<Vec<models::CompressedAggregateTradesListResponseInner>>(
            &self.configuration,
            "/dapi/v1/aggTrades",
            reqwest::Method::GET,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            false,
        )
        .await
    }

    async fn continuous_contract_kline_candlestick_data(
        &self,
        params: ContinuousContractKlineCandlestickDataParams,
    ) -> anyhow::Result<
        RestApiResponse<Vec<Vec<models::ContinuousContractKlineCandlestickDataResponseItemInner>>>,
    > {
        let ContinuousContractKlineCandlestickDataParams {
            pair,
            contract_type,
            interval,
            start_time,
            end_time,
            limit,
        } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        query_params.insert("pair".to_string(), json!(pair));

        query_params.insert("contractType".to_string(), json!(contract_type));

        query_params.insert("interval".to_string(), json!(interval));

        if let Some(rw) = start_time {
            query_params.insert("startTime".to_string(), json!(rw));
        }

        if let Some(rw) = end_time {
            query_params.insert("endTime".to_string(), json!(rw));
        }

        if let Some(rw) = limit {
            query_params.insert("limit".to_string(), json!(rw));
        }

        send_request::<Vec<Vec<models::ContinuousContractKlineCandlestickDataResponseItemInner>>>(
            &self.configuration,
            "/dapi/v1/continuousKlines",
            reqwest::Method::GET,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            false,
        )
        .await
    }

    async fn exchange_information(
        &self,
    ) -> anyhow::Result<RestApiResponse<models::ExchangeInformationResponse>> {
        let query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        send_request::<models::ExchangeInformationResponse>(
            &self.configuration,
            "/dapi/v1/exchangeInfo",
            reqwest::Method::GET,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            false,
        )
        .await
    }

    async fn get_funding_rate_history_of_perpetual_futures(
        &self,
        params: GetFundingRateHistoryOfPerpetualFuturesParams,
    ) -> anyhow::Result<
        RestApiResponse<Vec<models::GetFundingRateHistoryOfPerpetualFuturesResponseInner>>,
    > {
        let GetFundingRateHistoryOfPerpetualFuturesParams {
            symbol,
            start_time,
            end_time,
            limit,
        } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        query_params.insert("symbol".to_string(), json!(symbol));

        if let Some(rw) = start_time {
            query_params.insert("startTime".to_string(), json!(rw));
        }

        if let Some(rw) = end_time {
            query_params.insert("endTime".to_string(), json!(rw));
        }

        if let Some(rw) = limit {
            query_params.insert("limit".to_string(), json!(rw));
        }

        send_request::<Vec<models::GetFundingRateHistoryOfPerpetualFuturesResponseInner>>(
            &self.configuration,
            "/dapi/v1/fundingRate",
            reqwest::Method::GET,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            false,
        )
        .await
    }

    async fn get_funding_rate_info(
        &self,
    ) -> anyhow::Result<RestApiResponse<Vec<models::GetFundingRateInfoResponseInner>>> {
        let query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        send_request::<Vec<models::GetFundingRateInfoResponseInner>>(
            &self.configuration,
            "/dapi/v1/fundingInfo",
            reqwest::Method::GET,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            false,
        )
        .await
    }

    async fn index_price_and_mark_price(
        &self,
        params: IndexPriceAndMarkPriceParams,
    ) -> anyhow::Result<RestApiResponse<Vec<models::IndexPriceAndMarkPriceResponseInner>>> {
        let IndexPriceAndMarkPriceParams { symbol, pair } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        if let Some(rw) = symbol {
            query_params.insert("symbol".to_string(), json!(rw));
        }

        if let Some(rw) = pair {
            query_params.insert("pair".to_string(), json!(rw));
        }

        send_request::<Vec<models::IndexPriceAndMarkPriceResponseInner>>(
            &self.configuration,
            "/dapi/v1/premiumIndex",
            reqwest::Method::GET,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            false,
        )
        .await
    }

    async fn index_price_kline_candlestick_data(
        &self,
        params: IndexPriceKlineCandlestickDataParams,
    ) -> anyhow::Result<
        RestApiResponse<Vec<Vec<models::IndexPriceKlineCandlestickDataResponseItemInner>>>,
    > {
        let IndexPriceKlineCandlestickDataParams {
            pair,
            interval,
            start_time,
            end_time,
            limit,
        } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        query_params.insert("pair".to_string(), json!(pair));

        query_params.insert("interval".to_string(), json!(interval));

        if let Some(rw) = start_time {
            query_params.insert("startTime".to_string(), json!(rw));
        }

        if let Some(rw) = end_time {
            query_params.insert("endTime".to_string(), json!(rw));
        }

        if let Some(rw) = limit {
            query_params.insert("limit".to_string(), json!(rw));
        }

        send_request::<Vec<Vec<models::IndexPriceKlineCandlestickDataResponseItemInner>>>(
            &self.configuration,
            "/dapi/v1/indexPriceKlines",
            reqwest::Method::GET,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            false,
        )
        .await
    }

    async fn kline_candlestick_data(
        &self,
        params: KlineCandlestickDataParams,
    ) -> anyhow::Result<
        RestApiResponse<Vec<Vec<models::ContinuousContractKlineCandlestickDataResponseItemInner>>>,
    > {
        let KlineCandlestickDataParams {
            symbol,
            interval,
            start_time,
            end_time,
            limit,
        } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        query_params.insert("symbol".to_string(), json!(symbol));

        query_params.insert("interval".to_string(), json!(interval));

        if let Some(rw) = start_time {
            query_params.insert("startTime".to_string(), json!(rw));
        }

        if let Some(rw) = end_time {
            query_params.insert("endTime".to_string(), json!(rw));
        }

        if let Some(rw) = limit {
            query_params.insert("limit".to_string(), json!(rw));
        }

        send_request::<Vec<Vec<models::ContinuousContractKlineCandlestickDataResponseItemInner>>>(
            &self.configuration,
            "/dapi/v1/klines",
            reqwest::Method::GET,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            false,
        )
        .await
    }

    async fn long_short_ratio(
        &self,
        params: LongShortRatioParams,
    ) -> anyhow::Result<RestApiResponse<Vec<models::LongShortRatioResponseInner>>> {
        let LongShortRatioParams {
            pair,
            period,
            limit,
            start_time,
            end_time,
        } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        query_params.insert("pair".to_string(), json!(pair));

        query_params.insert("period".to_string(), json!(period));

        if let Some(rw) = limit {
            query_params.insert("limit".to_string(), json!(rw));
        }

        if let Some(rw) = start_time {
            query_params.insert("startTime".to_string(), json!(rw));
        }

        if let Some(rw) = end_time {
            query_params.insert("endTime".to_string(), json!(rw));
        }

        send_request::<Vec<models::LongShortRatioResponseInner>>(
            &self.configuration,
            "/futures/data/globalLongShortAccountRatio",
            reqwest::Method::GET,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            false,
        )
        .await
    }

    async fn mark_price_kline_candlestick_data(
        &self,
        params: MarkPriceKlineCandlestickDataParams,
    ) -> anyhow::Result<
        RestApiResponse<Vec<Vec<models::MarkPriceKlineCandlestickDataResponseItemInner>>>,
    > {
        let MarkPriceKlineCandlestickDataParams {
            symbol,
            interval,
            start_time,
            end_time,
            limit,
        } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        query_params.insert("symbol".to_string(), json!(symbol));

        query_params.insert("interval".to_string(), json!(interval));

        if let Some(rw) = start_time {
            query_params.insert("startTime".to_string(), json!(rw));
        }

        if let Some(rw) = end_time {
            query_params.insert("endTime".to_string(), json!(rw));
        }

        if let Some(rw) = limit {
            query_params.insert("limit".to_string(), json!(rw));
        }

        send_request::<Vec<Vec<models::MarkPriceKlineCandlestickDataResponseItemInner>>>(
            &self.configuration,
            "/dapi/v1/markPriceKlines",
            reqwest::Method::GET,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            false,
        )
        .await
    }

    async fn old_trades_lookup(
        &self,
        params: OldTradesLookupParams,
    ) -> anyhow::Result<RestApiResponse<Vec<models::OldTradesLookupResponseInner>>> {
        let OldTradesLookupParams {
            symbol,
            limit,
            from_id,
        } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        query_params.insert("symbol".to_string(), json!(symbol));

        if let Some(rw) = limit {
            query_params.insert("limit".to_string(), json!(rw));
        }

        if let Some(rw) = from_id {
            query_params.insert("fromId".to_string(), json!(rw));
        }

        send_request::<Vec<models::OldTradesLookupResponseInner>>(
            &self.configuration,
            "/dapi/v1/historicalTrades",
            reqwest::Method::GET,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            false,
        )
        .await
    }

    async fn open_interest(
        &self,
        params: OpenInterestParams,
    ) -> anyhow::Result<RestApiResponse<models::OpenInterestResponse>> {
        let OpenInterestParams { symbol } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        query_params.insert("symbol".to_string(), json!(symbol));

        send_request::<models::OpenInterestResponse>(
            &self.configuration,
            "/dapi/v1/openInterest",
            reqwest::Method::GET,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            false,
        )
        .await
    }

    async fn open_interest_statistics(
        &self,
        params: OpenInterestStatisticsParams,
    ) -> anyhow::Result<RestApiResponse<Vec<models::OpenInterestStatisticsResponseInner>>> {
        let OpenInterestStatisticsParams {
            pair,
            contract_type,
            period,
            limit,
            start_time,
            end_time,
        } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        query_params.insert("pair".to_string(), json!(pair));

        query_params.insert("contractType".to_string(), json!(contract_type));

        query_params.insert("period".to_string(), json!(period));

        if let Some(rw) = limit {
            query_params.insert("limit".to_string(), json!(rw));
        }

        if let Some(rw) = start_time {
            query_params.insert("startTime".to_string(), json!(rw));
        }

        if let Some(rw) = end_time {
            query_params.insert("endTime".to_string(), json!(rw));
        }

        send_request::<Vec<models::OpenInterestStatisticsResponseInner>>(
            &self.configuration,
            "/futures/data/openInterestHist",
            reqwest::Method::GET,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            false,
        )
        .await
    }

    async fn order_book(
        &self,
        params: OrderBookParams,
    ) -> anyhow::Result<RestApiResponse<models::OrderBookResponse>> {
        let OrderBookParams { symbol, limit } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        query_params.insert("symbol".to_string(), json!(symbol));

        if let Some(rw) = limit {
            query_params.insert("limit".to_string(), json!(rw));
        }

        send_request::<models::OrderBookResponse>(
            &self.configuration,
            "/dapi/v1/depth",
            reqwest::Method::GET,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            false,
        )
        .await
    }

    async fn premium_index_kline_data(
        &self,
        params: PremiumIndexKlineDataParams,
    ) -> anyhow::Result<RestApiResponse<Vec<Vec<models::PremiumIndexKlineDataResponseItemInner>>>>
    {
        let PremiumIndexKlineDataParams {
            symbol,
            interval,
            start_time,
            end_time,
            limit,
        } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        query_params.insert("symbol".to_string(), json!(symbol));

        query_params.insert("interval".to_string(), json!(interval));

        if let Some(rw) = start_time {
            query_params.insert("startTime".to_string(), json!(rw));
        }

        if let Some(rw) = end_time {
            query_params.insert("endTime".to_string(), json!(rw));
        }

        if let Some(rw) = limit {
            query_params.insert("limit".to_string(), json!(rw));
        }

        send_request::<Vec<Vec<models::PremiumIndexKlineDataResponseItemInner>>>(
            &self.configuration,
            "/dapi/v1/premiumIndexKlines",
            reqwest::Method::GET,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            false,
        )
        .await
    }

    async fn query_index_price_constituents(
        &self,
        params: QueryIndexPriceConstituentsParams,
    ) -> anyhow::Result<RestApiResponse<models::QueryIndexPriceConstituentsResponse>> {
        let QueryIndexPriceConstituentsParams { symbol } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        query_params.insert("symbol".to_string(), json!(symbol));

        send_request::<models::QueryIndexPriceConstituentsResponse>(
            &self.configuration,
            "/dapi/v1/constituents",
            reqwest::Method::GET,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            false,
        )
        .await
    }

    async fn recent_trades_list(
        &self,
        params: RecentTradesListParams,
    ) -> anyhow::Result<RestApiResponse<Vec<models::RecentTradesListResponseInner>>> {
        let RecentTradesListParams { symbol, limit } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        query_params.insert("symbol".to_string(), json!(symbol));

        if let Some(rw) = limit {
            query_params.insert("limit".to_string(), json!(rw));
        }

        send_request::<Vec<models::RecentTradesListResponseInner>>(
            &self.configuration,
            "/dapi/v1/trades",
            reqwest::Method::GET,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            false,
        )
        .await
    }

    async fn symbol_order_book_ticker(
        &self,
        params: SymbolOrderBookTickerParams,
    ) -> anyhow::Result<RestApiResponse<Vec<models::SymbolOrderBookTickerResponseInner>>> {
        let SymbolOrderBookTickerParams { symbol, pair } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        if let Some(rw) = symbol {
            query_params.insert("symbol".to_string(), json!(rw));
        }

        if let Some(rw) = pair {
            query_params.insert("pair".to_string(), json!(rw));
        }

        send_request::<Vec<models::SymbolOrderBookTickerResponseInner>>(
            &self.configuration,
            "/dapi/v1/ticker/bookTicker",
            reqwest::Method::GET,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            false,
        )
        .await
    }

    async fn symbol_price_ticker(
        &self,
        params: SymbolPriceTickerParams,
    ) -> anyhow::Result<RestApiResponse<Vec<models::SymbolPriceTickerResponseInner>>> {
        let SymbolPriceTickerParams { symbol, pair } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        if let Some(rw) = symbol {
            query_params.insert("symbol".to_string(), json!(rw));
        }

        if let Some(rw) = pair {
            query_params.insert("pair".to_string(), json!(rw));
        }

        send_request::<Vec<models::SymbolPriceTickerResponseInner>>(
            &self.configuration,
            "/dapi/v1/ticker/price",
            reqwest::Method::GET,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            false,
        )
        .await
    }

    async fn taker_buy_sell_volume(
        &self,
        params: TakerBuySellVolumeParams,
    ) -> anyhow::Result<RestApiResponse<Vec<models::TakerBuySellVolumeResponseInner>>> {
        let TakerBuySellVolumeParams {
            pair,
            contract_type,
            period,
            limit,
            start_time,
            end_time,
        } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        query_params.insert("pair".to_string(), json!(pair));

        query_params.insert("contractType".to_string(), json!(contract_type));

        query_params.insert("period".to_string(), json!(period));

        if let Some(rw) = limit {
            query_params.insert("limit".to_string(), json!(rw));
        }

        if let Some(rw) = start_time {
            query_params.insert("startTime".to_string(), json!(rw));
        }

        if let Some(rw) = end_time {
            query_params.insert("endTime".to_string(), json!(rw));
        }

        send_request::<Vec<models::TakerBuySellVolumeResponseInner>>(
            &self.configuration,
            "/futures/data/takerBuySellVol",
            reqwest::Method::GET,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            false,
        )
        .await
    }

    async fn test_connectivity(&self) -> anyhow::Result<RestApiResponse<Value>> {
        let query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        send_request::<Value>(
            &self.configuration,
            "/dapi/v1/ping",
            reqwest::Method::GET,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            false,
        )
        .await
    }

    async fn ticker24hr_price_change_statistics(
        &self,
        params: Ticker24hrPriceChangeStatisticsParams,
    ) -> anyhow::Result<RestApiResponse<Vec<models::Ticker24hrPriceChangeStatisticsResponseInner>>>
    {
        let Ticker24hrPriceChangeStatisticsParams { symbol, pair } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        if let Some(rw) = symbol {
            query_params.insert("symbol".to_string(), json!(rw));
        }

        if let Some(rw) = pair {
            query_params.insert("pair".to_string(), json!(rw));
        }

        send_request::<Vec<models::Ticker24hrPriceChangeStatisticsResponseInner>>(
            &self.configuration,
            "/dapi/v1/ticker/24hr",
            reqwest::Method::GET,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            false,
        )
        .await
    }

    async fn top_trader_long_short_ratio_accounts(
        &self,
        params: TopTraderLongShortRatioAccountsParams,
    ) -> anyhow::Result<RestApiResponse<Vec<models::TopTraderLongShortRatioAccountsResponseInner>>>
    {
        let TopTraderLongShortRatioAccountsParams {
            symbol,
            period,
            limit,
            start_time,
            end_time,
        } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        query_params.insert("symbol".to_string(), json!(symbol));

        query_params.insert("period".to_string(), json!(period));

        if let Some(rw) = limit {
            query_params.insert("limit".to_string(), json!(rw));
        }

        if let Some(rw) = start_time {
            query_params.insert("startTime".to_string(), json!(rw));
        }

        if let Some(rw) = end_time {
            query_params.insert("endTime".to_string(), json!(rw));
        }

        send_request::<Vec<models::TopTraderLongShortRatioAccountsResponseInner>>(
            &self.configuration,
            "/futures/data/topLongShortAccountRatio",
            reqwest::Method::GET,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            false,
        )
        .await
    }

    async fn top_trader_long_short_ratio_positions(
        &self,
        params: TopTraderLongShortRatioPositionsParams,
    ) -> anyhow::Result<RestApiResponse<Vec<models::TopTraderLongShortRatioPositionsResponseInner>>>
    {
        let TopTraderLongShortRatioPositionsParams {
            pair,
            period,
            limit,
            start_time,
            end_time,
        } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        query_params.insert("pair".to_string(), json!(pair));

        query_params.insert("period".to_string(), json!(period));

        if let Some(rw) = limit {
            query_params.insert("limit".to_string(), json!(rw));
        }

        if let Some(rw) = start_time {
            query_params.insert("startTime".to_string(), json!(rw));
        }

        if let Some(rw) = end_time {
            query_params.insert("endTime".to_string(), json!(rw));
        }

        send_request::<Vec<models::TopTraderLongShortRatioPositionsResponseInner>>(
            &self.configuration,
            "/futures/data/topLongShortPositionRatio",
            reqwest::Method::GET,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            false,
        )
        .await
    }
}

#[cfg(all(test, feature = "derivatives_trading_coin_futures"))]
mod tests {
    use super::*;
    use crate::TOKIO_SHARED_RT;
    use crate::{errors::ConnectorError, models::DataFuture, models::RestApiRateLimit};
    use async_trait::async_trait;
    use std::collections::HashMap;

    struct DummyRestApiResponse<T> {
        inner: Box<dyn FnOnce() -> DataFuture<Result<T, ConnectorError>> + Send + Sync>,
        status: u16,
        headers: HashMap<String, String>,
        rate_limits: Option<Vec<RestApiRateLimit>>,
    }

    impl<T> From<DummyRestApiResponse<T>> for RestApiResponse<T> {
        fn from(dummy: DummyRestApiResponse<T>) -> Self {
            Self {
                data_fn: dummy.inner,
                status: dummy.status,
                headers: dummy.headers,
                rate_limits: dummy.rate_limits,
            }
        }
    }

    struct MockMarketDataApiClient {
        force_error: bool,
    }

    #[async_trait]
    impl MarketDataApi for MockMarketDataApiClient {
        async fn basis(
            &self,
            _params: BasisParams,
        ) -> anyhow::Result<RestApiResponse<Vec<models::BasisResponseInner>>> {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            let resp_json: Value = serde_json::from_str(r#"[{"indexPrice":"29269.93972727","contractType":"CURRENT_QUARTER","basisRate":"0.0024","futuresPrice":"29341.3","annualizedBasisRate":"0.0283","basis":"71.36027273","pair":"BTCUSD","timestamp":1653381600000}]"#).unwrap();
            let dummy_response: Vec<models::BasisResponseInner> =
                serde_json::from_value(resp_json.clone())
                    .expect("should parse into Vec<models::BasisResponseInner>");

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn check_server_time(
            &self,
        ) -> anyhow::Result<RestApiResponse<models::CheckServerTimeResponse>> {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            let resp_json: Value = serde_json::from_str(r#"{"serverTime":1499827319559}"#).unwrap();
            let dummy_response: models::CheckServerTimeResponse =
                serde_json::from_value(resp_json.clone())
                    .expect("should parse into models::CheckServerTimeResponse");

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn compressed_aggregate_trades_list(
            &self,
            _params: CompressedAggregateTradesListParams,
        ) -> anyhow::Result<RestApiResponse<Vec<models::CompressedAggregateTradesListResponseInner>>>
        {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            let resp_json: Value = serde_json::from_str(r#"[{"a":416690,"p":"9642.4","q":"3","f":595259,"l":595259,"T":1591250548649,"m":false}]"#).unwrap();
            let dummy_response: Vec<models::CompressedAggregateTradesListResponseInner> =
                serde_json::from_value(resp_json.clone()).expect(
                    "should parse into Vec<models::CompressedAggregateTradesListResponseInner>",
                );

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn continuous_contract_kline_candlestick_data(
            &self,
            _params: ContinuousContractKlineCandlestickDataParams,
        ) -> anyhow::Result<
            RestApiResponse<
                Vec<Vec<models::ContinuousContractKlineCandlestickDataResponseItemInner>>,
            >,
        > {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            let resp_json: Value = serde_json::from_str(r#"[[1591258320000,"9640.7","9642.4","9640.6","9642.0","206",1591258379999,"2.13660389",48,"119","1.23424865","0"]]"#).unwrap();
            let dummy_response : Vec<Vec<models::ContinuousContractKlineCandlestickDataResponseItemInner>> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<Vec<models::ContinuousContractKlineCandlestickDataResponseItemInner>>");

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn exchange_information(
            &self,
        ) -> anyhow::Result<RestApiResponse<models::ExchangeInformationResponse>> {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            let resp_json: Value = serde_json::from_str(r#"{"exchangeFilters":[],"rateLimits":[{"interval":"MINUTE","intervalNum":1,"limit":6000,"rateLimitType":"REQUEST_WEIGHT"},{"interval":"MINUTE","intervalNum":1,"limit":6000,"rateLimitType":"ORDERS"}],"serverTime":1565613908500,"symbols":[{"filters":[{"filterType":"PRICE_FILTER","maxPrice":"100000","minPrice":"0.1","tickSize":"0.1"},{"filterType":"LOT_SIZE","maxQty":"100000","minQty":"1","stepSize":"1"},{"filterType":"MARKET_LOT_SIZE","maxQty":"100000","minQty":"1","stepSize":"1"},{"filterType":"MAX_NUM_ORDERS","limit":200},{"filterType":"PERCENT_PRICE","multiplierUp":"1.0500","multiplierDown":"0.9500","multiplierDecimal":"4"}],"orderTypes":["LIMIT","MARKET","STOP","TAKE_PROFIT","TRAILING_STOP_MARKET"],"timeInForce":["GTC","IOC","FOK","GTX"],"liquidationFee":"0.010000","marketTakeBound":"0.30","symbol":"BTCUSD_200925","pair":"BTCUSD","contractType":"CURRENT_QUARTER","deliveryDate":1601020800000,"onboardDate":1590739200000,"contractStatus":"TRADING","contractSize":100,"quoteAsset":"USD","baseAsset":"BTC","marginAsset":"BTC","pricePrecision":1,"quantityPrecision":0,"baseAssetPrecision":8,"quotePrecision":8,"equalQtyPrecision":4,"triggerProtect":"0.0500","maintMarginPercent":"2.5000","requiredMarginPercent":"5.0000","underlyingType":"COIN","underlyingSubType":[]}],"timezone":"UTC"}"#).unwrap();
            let dummy_response: models::ExchangeInformationResponse =
                serde_json::from_value(resp_json.clone())
                    .expect("should parse into models::ExchangeInformationResponse");

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn get_funding_rate_history_of_perpetual_futures(
            &self,
            _params: GetFundingRateHistoryOfPerpetualFuturesParams,
        ) -> anyhow::Result<
            RestApiResponse<Vec<models::GetFundingRateHistoryOfPerpetualFuturesResponseInner>>,
        > {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            let resp_json: Value = serde_json::from_str(r#"[{"symbol":"BTCUSD_PERP","fundingTime":1596038400000,"fundingRate":"-0.00300000"},{"symbol":"BTCUSD_PERP","fundingTime":1596067200000,"fundingRate":"-0.00300000"}]"#).unwrap();
            let dummy_response : Vec<models::GetFundingRateHistoryOfPerpetualFuturesResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::GetFundingRateHistoryOfPerpetualFuturesResponseInner>");

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn get_funding_rate_info(
            &self,
        ) -> anyhow::Result<RestApiResponse<Vec<models::GetFundingRateInfoResponseInner>>> {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            let resp_json: Value = serde_json::from_str(r#"[{"symbol":"BTCUSD_PERP","adjustedFundingRateCap":"0.02500000","adjustedFundingRateFloor":"-0.02500000","fundingIntervalHours":8,"disclaimer":false}]"#).unwrap();
            let dummy_response: Vec<models::GetFundingRateInfoResponseInner> =
                serde_json::from_value(resp_json.clone())
                    .expect("should parse into Vec<models::GetFundingRateInfoResponseInner>");

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn index_price_and_mark_price(
            &self,
            _params: IndexPriceAndMarkPriceParams,
        ) -> anyhow::Result<RestApiResponse<Vec<models::IndexPriceAndMarkPriceResponseInner>>>
        {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            let resp_json: Value = serde_json::from_str(r#"[{"symbol":"BTCUSD_PERP","pair":"BTCUSD","markPrice":"11029.69574559","indexPrice":"10979.14437500","estimatedSettlePrice":"10981.74168236","lastFundingRate":"0.00071003","interestRate":"0.00010000","nextFundingTime":1596096000000,"time":1596094042000},{"symbol":"BTCUSD_200925","pair":"BTCUSD","markPrice":"12077.01343750","indexPrice":"10979.10312500","estimatedSettlePrice":"10981.74168236","lastFundingRate":"","interestRate":"","nextFundingTime":0,"time":1596094042000}]"#).unwrap();
            let dummy_response: Vec<models::IndexPriceAndMarkPriceResponseInner> =
                serde_json::from_value(resp_json.clone())
                    .expect("should parse into Vec<models::IndexPriceAndMarkPriceResponseInner>");

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn index_price_kline_candlestick_data(
            &self,
            _params: IndexPriceKlineCandlestickDataParams,
        ) -> anyhow::Result<
            RestApiResponse<Vec<Vec<models::IndexPriceKlineCandlestickDataResponseItemInner>>>,
        > {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            let resp_json: Value = serde_json::from_str(r#"[[1591256400000,"9653.69440000","9653.69640000","9651.38600000","9651.55200000","0",1591256459999,"0",60,"0","0","0"]]"#).unwrap();
            let dummy_response : Vec<Vec<models::IndexPriceKlineCandlestickDataResponseItemInner>> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<Vec<models::IndexPriceKlineCandlestickDataResponseItemInner>>");

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn kline_candlestick_data(
            &self,
            _params: KlineCandlestickDataParams,
        ) -> anyhow::Result<
            RestApiResponse<
                Vec<Vec<models::ContinuousContractKlineCandlestickDataResponseItemInner>>,
            >,
        > {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            let resp_json: Value = serde_json::from_str(r#"[[1591258320000,"9640.7","9642.4","9640.6","9642.0","206",1591258379999,"2.13660389",48,"119","1.23424865","0"]]"#).unwrap();
            let dummy_response : Vec<Vec<models::ContinuousContractKlineCandlestickDataResponseItemInner>> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<Vec<models::ContinuousContractKlineCandlestickDataResponseItemInner>>");

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn long_short_ratio(
            &self,
            _params: LongShortRatioParams,
        ) -> anyhow::Result<RestApiResponse<Vec<models::LongShortRatioResponseInner>>> {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            let resp_json: Value = serde_json::from_str(r#"[{"pair":"BTCUSD","longShortRatio":"0.1960","longAccount":"0.6622","shortAccount":"0.3378","timestamp":1583139600000},{"pair":"BTCUSD","longShortRatio":"1.9559","longAccount":"0.6617","shortAccount":"0.3382","timestamp":1583139900000}]"#).unwrap();
            let dummy_response: Vec<models::LongShortRatioResponseInner> =
                serde_json::from_value(resp_json.clone())
                    .expect("should parse into Vec<models::LongShortRatioResponseInner>");

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn mark_price_kline_candlestick_data(
            &self,
            _params: MarkPriceKlineCandlestickDataParams,
        ) -> anyhow::Result<
            RestApiResponse<Vec<Vec<models::MarkPriceKlineCandlestickDataResponseItemInner>>>,
        > {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            let resp_json: Value = serde_json::from_str(r#"[[1591256460000,"9653.29201333","9654.56401333","9653.07367333","9653.07367333","0",1591256519999,"0",60,"0","0","0"]]"#).unwrap();
            let dummy_response : Vec<Vec<models::MarkPriceKlineCandlestickDataResponseItemInner>> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<Vec<models::MarkPriceKlineCandlestickDataResponseItemInner>>");

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn old_trades_lookup(
            &self,
            _params: OldTradesLookupParams,
        ) -> anyhow::Result<RestApiResponse<Vec<models::OldTradesLookupResponseInner>>> {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            let resp_json: Value = serde_json::from_str(r#"[{"id":595103,"price":"9642.2","qty":"1","baseQty":"0.01037108","time":1499865549590,"isBuyerMaker":true}]"#).unwrap();
            let dummy_response: Vec<models::OldTradesLookupResponseInner> =
                serde_json::from_value(resp_json.clone())
                    .expect("should parse into Vec<models::OldTradesLookupResponseInner>");

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn open_interest(
            &self,
            _params: OpenInterestParams,
        ) -> anyhow::Result<RestApiResponse<models::OpenInterestResponse>> {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            let resp_json: Value = serde_json::from_str(r#"{"symbol":"BTCUSD_200626","pair":"BTCUSD","openInterest":"15004","contractType":"CURRENT_QUARTER","time":1591261042378}"#).unwrap();
            let dummy_response: models::OpenInterestResponse =
                serde_json::from_value(resp_json.clone())
                    .expect("should parse into models::OpenInterestResponse");

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn open_interest_statistics(
            &self,
            _params: OpenInterestStatisticsParams,
        ) -> anyhow::Result<RestApiResponse<Vec<models::OpenInterestStatisticsResponseInner>>>
        {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            let resp_json: Value = serde_json::from_str(r#"[{"pair":"BTCUSD","contractType":"CURRENT_QUARTER","sumOpenInterest":"20403","sumOpenInterestValue":"176196512.23400000","timestamp":1591261042378},{"pair":"BTCUSD","contractType":"CURRENT_QUARTER","sumOpenInterest":"20401","sumOpenInterestValue":"176178704.98700000","timestamp":1583128200000}]"#).unwrap();
            let dummy_response: Vec<models::OpenInterestStatisticsResponseInner> =
                serde_json::from_value(resp_json.clone())
                    .expect("should parse into Vec<models::OpenInterestStatisticsResponseInner>");

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn order_book(
            &self,
            _params: OrderBookParams,
        ) -> anyhow::Result<RestApiResponse<models::OrderBookResponse>> {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            let resp_json: Value = serde_json::from_str(r#"{"lastUpdateId":16769853,"symbol":"BTCUSD_PERP","pair":"BTCUSD","E":1591250106370,"T":1591250106368,"bids":[["9638.0","431"]],"asks":[["9638.2","12"]]}"#).unwrap();
            let dummy_response: models::OrderBookResponse =
                serde_json::from_value(resp_json.clone())
                    .expect("should parse into models::OrderBookResponse");

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn premium_index_kline_data(
            &self,
            _params: PremiumIndexKlineDataParams,
        ) -> anyhow::Result<RestApiResponse<Vec<Vec<models::PremiumIndexKlineDataResponseItemInner>>>>
        {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            let resp_json: Value = serde_json::from_str(r#"[[1691603820000,"-0.00042931","-0.00023641","-0.00059406","-0.00043659","0",1691603879999,"0",12,"0","0","0"]]"#).unwrap();
            let dummy_response: Vec<Vec<models::PremiumIndexKlineDataResponseItemInner>> =
                serde_json::from_value(resp_json.clone()).expect(
                    "should parse into Vec<Vec<models::PremiumIndexKlineDataResponseItemInner>>",
                );

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn query_index_price_constituents(
            &self,
            _params: QueryIndexPriceConstituentsParams,
        ) -> anyhow::Result<RestApiResponse<models::QueryIndexPriceConstituentsResponse>> {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            let resp_json: Value = serde_json::from_str(r#"{"symbol":"BTCUSD","time":1697422647853,"constituents":[{"exchange":"bitstamp","symbol":"btcusd"},{"exchange":"coinbase","symbol":"BTC-USD"},{"exchange":"kraken","symbol":"XBT/USD"},{"exchange":"binance_cross","symbol":"BTCUSDC*index(USDCUSD)"}]}"#).unwrap();
            let dummy_response: models::QueryIndexPriceConstituentsResponse =
                serde_json::from_value(resp_json.clone())
                    .expect("should parse into models::QueryIndexPriceConstituentsResponse");

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn recent_trades_list(
            &self,
            _params: RecentTradesListParams,
        ) -> anyhow::Result<RestApiResponse<Vec<models::RecentTradesListResponseInner>>> {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            let resp_json: Value = serde_json::from_str(r#"[{"id":28457,"price":"9635.0","qty":"1","baseQty":"0.01037883","time":1591250192508,"isBuyerMaker":true}]"#).unwrap();
            let dummy_response: Vec<models::RecentTradesListResponseInner> =
                serde_json::from_value(resp_json.clone())
                    .expect("should parse into Vec<models::RecentTradesListResponseInner>");

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn symbol_order_book_ticker(
            &self,
            _params: SymbolOrderBookTickerParams,
        ) -> anyhow::Result<RestApiResponse<Vec<models::SymbolOrderBookTickerResponseInner>>>
        {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            let resp_json: Value = serde_json::from_str(r#"[{"lastUpdateId":1027024,"symbol":"BTCUSD_200626","pair":"BTCUSD","bidPrice":"9650.1","bidQty":"16","askPrice":"9650.3","askQty":"7","time":1591257300345}]"#).unwrap();
            let dummy_response: Vec<models::SymbolOrderBookTickerResponseInner> =
                serde_json::from_value(resp_json.clone())
                    .expect("should parse into Vec<models::SymbolOrderBookTickerResponseInner>");

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn symbol_price_ticker(
            &self,
            _params: SymbolPriceTickerParams,
        ) -> anyhow::Result<RestApiResponse<Vec<models::SymbolPriceTickerResponseInner>>> {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            let resp_json: Value = serde_json::from_str(r#"[{"symbol":"BTCUSD_200626","ps":"9647.8","price":"9647.8","time":1591257246176}]"#).unwrap();
            let dummy_response: Vec<models::SymbolPriceTickerResponseInner> =
                serde_json::from_value(resp_json.clone())
                    .expect("should parse into Vec<models::SymbolPriceTickerResponseInner>");

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn taker_buy_sell_volume(
            &self,
            _params: TakerBuySellVolumeParams,
        ) -> anyhow::Result<RestApiResponse<Vec<models::TakerBuySellVolumeResponseInner>>> {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            let resp_json: Value = serde_json::from_str(r#"[{"pair":"BTCUSD","contractType":"CURRENT_QUARTER","takerBuyVol":"387","takerSellVol":"248","takerBuyVolValue":"2342.1220","takerSellVolValue":"4213.9800","timestamp":1591261042378},{"pair":"BTCUSD","contractType":"CURRENT_QUARTER","takerBuyVol":"234","takerSellVol":"121","takerBuyVolValue":"4563.1320","takerSellVolValue":"3313.3940","timestamp":1585615200000}]"#).unwrap();
            let dummy_response: Vec<models::TakerBuySellVolumeResponseInner> =
                serde_json::from_value(resp_json.clone())
                    .expect("should parse into Vec<models::TakerBuySellVolumeResponseInner>");

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn test_connectivity(&self) -> anyhow::Result<RestApiResponse<Value>> {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            let dummy_response = Value::Null;

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn ticker24hr_price_change_statistics(
            &self,
            _params: Ticker24hrPriceChangeStatisticsParams,
        ) -> anyhow::Result<
            RestApiResponse<Vec<models::Ticker24hrPriceChangeStatisticsResponseInner>>,
        > {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            let resp_json: Value = serde_json::from_str(r#"[{"symbol":"BTCUSD_200925","pair":"BTCUSD","priceChange":"136.6","priceChangePercent":"1.436","weightedAvgPrice":"9547.3","lastPrice":"9651.6","lastQty":"1","openPrice":"9515.0","highPrice":"9687.0","lowPrice":"9499.5","volume":"494109","baseVolume":"5192.94797687","openTime":1591170300000,"closeTime":1591256718418,"firstId":600507,"lastId":697803,"count":97297}]"#).unwrap();
            let dummy_response: Vec<models::Ticker24hrPriceChangeStatisticsResponseInner> =
                serde_json::from_value(resp_json.clone()).expect(
                    "should parse into Vec<models::Ticker24hrPriceChangeStatisticsResponseInner>",
                );

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn top_trader_long_short_ratio_accounts(
            &self,
            _params: TopTraderLongShortRatioAccountsParams,
        ) -> anyhow::Result<
            RestApiResponse<Vec<models::TopTraderLongShortRatioAccountsResponseInner>>,
        > {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            let resp_json: Value = serde_json::from_str(r#"[{"pair":"BTCUSD","longShortRatio":"1.8105","longAccount":"0.6442","shortAccount":"0.3558","timestamp":1591261042378},{"pair":"BTCUSD","longShortRatio":"1.1110","longAccount":"0.5263","shortAccount":"0.4737","timestamp":1592870400000}]"#).unwrap();
            let dummy_response: Vec<models::TopTraderLongShortRatioAccountsResponseInner> =
                serde_json::from_value(resp_json.clone()).expect(
                    "should parse into Vec<models::TopTraderLongShortRatioAccountsResponseInner>",
                );

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn top_trader_long_short_ratio_positions(
            &self,
            _params: TopTraderLongShortRatioPositionsParams,
        ) -> anyhow::Result<
            RestApiResponse<Vec<models::TopTraderLongShortRatioPositionsResponseInner>>,
        > {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            let resp_json: Value = serde_json::from_str(r#"[{"pair":"BTCUSD","longShortRatio":"0.7869","longPosition":"0.6442","shortPosition":"0.4404","timestamp":1592870400000},{"pair":"BTCUSD","longShortRatio":"1.1231","longPosition":"0.2363","shortPosition":"0.4537","timestamp":1592956800000}]"#).unwrap();
            let dummy_response: Vec<models::TopTraderLongShortRatioPositionsResponseInner> =
                serde_json::from_value(resp_json.clone()).expect(
                    "should parse into Vec<models::TopTraderLongShortRatioPositionsResponseInner>",
                );

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }
    }

    #[test]
    fn basis_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: false };

            let params = BasisParams::builder("pair_example".to_string(),BasisContractTypeEnum::Perpetual,BasisPeriodEnum::Period5m,).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"[{"indexPrice":"29269.93972727","contractType":"CURRENT_QUARTER","basisRate":"0.0024","futuresPrice":"29341.3","annualizedBasisRate":"0.0283","basis":"71.36027273","pair":"BTCUSD","timestamp":1653381600000}]"#).unwrap();
            let expected_response : Vec<models::BasisResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::BasisResponseInner>");

            let resp = client.basis(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn basis_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: false };

            let params = BasisParams::builder("pair_example".to_string(),BasisContractTypeEnum::Perpetual,BasisPeriodEnum::Period5m,).limit(100).start_time(1623319461670).end_time(1641782889000).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"[{"indexPrice":"29269.93972727","contractType":"CURRENT_QUARTER","basisRate":"0.0024","futuresPrice":"29341.3","annualizedBasisRate":"0.0283","basis":"71.36027273","pair":"BTCUSD","timestamp":1653381600000}]"#).unwrap();
            let expected_response : Vec<models::BasisResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::BasisResponseInner>");

            let resp = client.basis(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn basis_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: true };

            let params = BasisParams::builder(
                "pair_example".to_string(),
                BasisContractTypeEnum::Perpetual,
                BasisPeriodEnum::Period5m,
            )
            .build()
            .unwrap();

            match client.basis(params).await {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn check_server_time_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: false };

            let resp_json: Value = serde_json::from_str(r#"{"serverTime":1499827319559}"#).unwrap();
            let expected_response: models::CheckServerTimeResponse =
                serde_json::from_value(resp_json.clone())
                    .expect("should parse into models::CheckServerTimeResponse");

            let resp = client
                .check_server_time()
                .await
                .expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn check_server_time_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: false };

            let resp_json: Value = serde_json::from_str(r#"{"serverTime":1499827319559}"#).unwrap();
            let expected_response: models::CheckServerTimeResponse =
                serde_json::from_value(resp_json.clone())
                    .expect("should parse into models::CheckServerTimeResponse");

            let resp = client
                .check_server_time()
                .await
                .expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn check_server_time_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: true };

            match client.check_server_time().await {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn compressed_aggregate_trades_list_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: false };

            let params = CompressedAggregateTradesListParams::builder("symbol_example".to_string(),).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"[{"a":416690,"p":"9642.4","q":"3","f":595259,"l":595259,"T":1591250548649,"m":false}]"#).unwrap();
            let expected_response : Vec<models::CompressedAggregateTradesListResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::CompressedAggregateTradesListResponseInner>");

            let resp = client.compressed_aggregate_trades_list(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn compressed_aggregate_trades_list_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: false };

            let params = CompressedAggregateTradesListParams::builder("symbol_example".to_string(),).from_id(1).start_time(1623319461670).end_time(1641782889000).limit(100).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"[{"a":416690,"p":"9642.4","q":"3","f":595259,"l":595259,"T":1591250548649,"m":false}]"#).unwrap();
            let expected_response : Vec<models::CompressedAggregateTradesListResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::CompressedAggregateTradesListResponseInner>");

            let resp = client.compressed_aggregate_trades_list(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn compressed_aggregate_trades_list_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: true };

            let params = CompressedAggregateTradesListParams::builder("symbol_example".to_string())
                .build()
                .unwrap();

            match client.compressed_aggregate_trades_list(params).await {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn continuous_contract_kline_candlestick_data_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: false };

            let params = ContinuousContractKlineCandlestickDataParams::builder("pair_example".to_string(),ContinuousContractKlineCandlestickDataContractTypeEnum::Perpetual,ContinuousContractKlineCandlestickDataIntervalEnum::Interval1m,).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"[[1591258320000,"9640.7","9642.4","9640.6","9642.0","206",1591258379999,"2.13660389",48,"119","1.23424865","0"]]"#).unwrap();
            let expected_response : Vec<Vec<models::ContinuousContractKlineCandlestickDataResponseItemInner>> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<Vec<models::ContinuousContractKlineCandlestickDataResponseItemInner>>");

            let resp = client.continuous_contract_kline_candlestick_data(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn continuous_contract_kline_candlestick_data_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: false };

            let params = ContinuousContractKlineCandlestickDataParams::builder("pair_example".to_string(),ContinuousContractKlineCandlestickDataContractTypeEnum::Perpetual,ContinuousContractKlineCandlestickDataIntervalEnum::Interval1m,).start_time(1623319461670).end_time(1641782889000).limit(100).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"[[1591258320000,"9640.7","9642.4","9640.6","9642.0","206",1591258379999,"2.13660389",48,"119","1.23424865","0"]]"#).unwrap();
            let expected_response : Vec<Vec<models::ContinuousContractKlineCandlestickDataResponseItemInner>> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<Vec<models::ContinuousContractKlineCandlestickDataResponseItemInner>>");

            let resp = client.continuous_contract_kline_candlestick_data(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn continuous_contract_kline_candlestick_data_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: true };

            let params = ContinuousContractKlineCandlestickDataParams::builder(
                "pair_example".to_string(),
                ContinuousContractKlineCandlestickDataContractTypeEnum::Perpetual,
                ContinuousContractKlineCandlestickDataIntervalEnum::Interval1m,
            )
            .build()
            .unwrap();

            match client
                .continuous_contract_kline_candlestick_data(params)
                .await
            {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn exchange_information_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: false };


            let resp_json: Value = serde_json::from_str(r#"{"exchangeFilters":[],"rateLimits":[{"interval":"MINUTE","intervalNum":1,"limit":6000,"rateLimitType":"REQUEST_WEIGHT"},{"interval":"MINUTE","intervalNum":1,"limit":6000,"rateLimitType":"ORDERS"}],"serverTime":1565613908500,"symbols":[{"filters":[{"filterType":"PRICE_FILTER","maxPrice":"100000","minPrice":"0.1","tickSize":"0.1"},{"filterType":"LOT_SIZE","maxQty":"100000","minQty":"1","stepSize":"1"},{"filterType":"MARKET_LOT_SIZE","maxQty":"100000","minQty":"1","stepSize":"1"},{"filterType":"MAX_NUM_ORDERS","limit":200},{"filterType":"PERCENT_PRICE","multiplierUp":"1.0500","multiplierDown":"0.9500","multiplierDecimal":"4"}],"orderTypes":["LIMIT","MARKET","STOP","TAKE_PROFIT","TRAILING_STOP_MARKET"],"timeInForce":["GTC","IOC","FOK","GTX"],"liquidationFee":"0.010000","marketTakeBound":"0.30","symbol":"BTCUSD_200925","pair":"BTCUSD","contractType":"CURRENT_QUARTER","deliveryDate":1601020800000,"onboardDate":1590739200000,"contractStatus":"TRADING","contractSize":100,"quoteAsset":"USD","baseAsset":"BTC","marginAsset":"BTC","pricePrecision":1,"quantityPrecision":0,"baseAssetPrecision":8,"quotePrecision":8,"equalQtyPrecision":4,"triggerProtect":"0.0500","maintMarginPercent":"2.5000","requiredMarginPercent":"5.0000","underlyingType":"COIN","underlyingSubType":[]}],"timezone":"UTC"}"#).unwrap();
            let expected_response : models::ExchangeInformationResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::ExchangeInformationResponse");

            let resp = client.exchange_information().await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn exchange_information_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: false };


            let resp_json: Value = serde_json::from_str(r#"{"exchangeFilters":[],"rateLimits":[{"interval":"MINUTE","intervalNum":1,"limit":6000,"rateLimitType":"REQUEST_WEIGHT"},{"interval":"MINUTE","intervalNum":1,"limit":6000,"rateLimitType":"ORDERS"}],"serverTime":1565613908500,"symbols":[{"filters":[{"filterType":"PRICE_FILTER","maxPrice":"100000","minPrice":"0.1","tickSize":"0.1"},{"filterType":"LOT_SIZE","maxQty":"100000","minQty":"1","stepSize":"1"},{"filterType":"MARKET_LOT_SIZE","maxQty":"100000","minQty":"1","stepSize":"1"},{"filterType":"MAX_NUM_ORDERS","limit":200},{"filterType":"PERCENT_PRICE","multiplierUp":"1.0500","multiplierDown":"0.9500","multiplierDecimal":"4"}],"orderTypes":["LIMIT","MARKET","STOP","TAKE_PROFIT","TRAILING_STOP_MARKET"],"timeInForce":["GTC","IOC","FOK","GTX"],"liquidationFee":"0.010000","marketTakeBound":"0.30","symbol":"BTCUSD_200925","pair":"BTCUSD","contractType":"CURRENT_QUARTER","deliveryDate":1601020800000,"onboardDate":1590739200000,"contractStatus":"TRADING","contractSize":100,"quoteAsset":"USD","baseAsset":"BTC","marginAsset":"BTC","pricePrecision":1,"quantityPrecision":0,"baseAssetPrecision":8,"quotePrecision":8,"equalQtyPrecision":4,"triggerProtect":"0.0500","maintMarginPercent":"2.5000","requiredMarginPercent":"5.0000","underlyingType":"COIN","underlyingSubType":[]}],"timezone":"UTC"}"#).unwrap();
            let expected_response : models::ExchangeInformationResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::ExchangeInformationResponse");

            let resp = client.exchange_information().await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn exchange_information_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: true };

            match client.exchange_information().await {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn get_funding_rate_history_of_perpetual_futures_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: false };

            let params = GetFundingRateHistoryOfPerpetualFuturesParams::builder("symbol_example".to_string(),).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"[{"symbol":"BTCUSD_PERP","fundingTime":1596038400000,"fundingRate":"-0.00300000"},{"symbol":"BTCUSD_PERP","fundingTime":1596067200000,"fundingRate":"-0.00300000"}]"#).unwrap();
            let expected_response : Vec<models::GetFundingRateHistoryOfPerpetualFuturesResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::GetFundingRateHistoryOfPerpetualFuturesResponseInner>");

            let resp = client.get_funding_rate_history_of_perpetual_futures(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn get_funding_rate_history_of_perpetual_futures_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: false };

            let params = GetFundingRateHistoryOfPerpetualFuturesParams::builder("symbol_example".to_string(),).start_time(1623319461670).end_time(1641782889000).limit(100).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"[{"symbol":"BTCUSD_PERP","fundingTime":1596038400000,"fundingRate":"-0.00300000"},{"symbol":"BTCUSD_PERP","fundingTime":1596067200000,"fundingRate":"-0.00300000"}]"#).unwrap();
            let expected_response : Vec<models::GetFundingRateHistoryOfPerpetualFuturesResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::GetFundingRateHistoryOfPerpetualFuturesResponseInner>");

            let resp = client.get_funding_rate_history_of_perpetual_futures(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn get_funding_rate_history_of_perpetual_futures_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: true };

            let params = GetFundingRateHistoryOfPerpetualFuturesParams::builder(
                "symbol_example".to_string(),
            )
            .build()
            .unwrap();

            match client
                .get_funding_rate_history_of_perpetual_futures(params)
                .await
            {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn get_funding_rate_info_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: false };


            let resp_json: Value = serde_json::from_str(r#"[{"symbol":"BTCUSD_PERP","adjustedFundingRateCap":"0.02500000","adjustedFundingRateFloor":"-0.02500000","fundingIntervalHours":8,"disclaimer":false}]"#).unwrap();
            let expected_response : Vec<models::GetFundingRateInfoResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::GetFundingRateInfoResponseInner>");

            let resp = client.get_funding_rate_info().await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn get_funding_rate_info_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: false };


            let resp_json: Value = serde_json::from_str(r#"[{"symbol":"BTCUSD_PERP","adjustedFundingRateCap":"0.02500000","adjustedFundingRateFloor":"-0.02500000","fundingIntervalHours":8,"disclaimer":false}]"#).unwrap();
            let expected_response : Vec<models::GetFundingRateInfoResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::GetFundingRateInfoResponseInner>");

            let resp = client.get_funding_rate_info().await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn get_funding_rate_info_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: true };

            match client.get_funding_rate_info().await {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn index_price_and_mark_price_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: false };

            let params = IndexPriceAndMarkPriceParams::builder().build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"[{"symbol":"BTCUSD_PERP","pair":"BTCUSD","markPrice":"11029.69574559","indexPrice":"10979.14437500","estimatedSettlePrice":"10981.74168236","lastFundingRate":"0.00071003","interestRate":"0.00010000","nextFundingTime":1596096000000,"time":1596094042000},{"symbol":"BTCUSD_200925","pair":"BTCUSD","markPrice":"12077.01343750","indexPrice":"10979.10312500","estimatedSettlePrice":"10981.74168236","lastFundingRate":"","interestRate":"","nextFundingTime":0,"time":1596094042000}]"#).unwrap();
            let expected_response : Vec<models::IndexPriceAndMarkPriceResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::IndexPriceAndMarkPriceResponseInner>");

            let resp = client.index_price_and_mark_price(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn index_price_and_mark_price_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: false };

            let params = IndexPriceAndMarkPriceParams::builder().symbol("symbol_example".to_string()).pair("pair_example".to_string()).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"[{"symbol":"BTCUSD_PERP","pair":"BTCUSD","markPrice":"11029.69574559","indexPrice":"10979.14437500","estimatedSettlePrice":"10981.74168236","lastFundingRate":"0.00071003","interestRate":"0.00010000","nextFundingTime":1596096000000,"time":1596094042000},{"symbol":"BTCUSD_200925","pair":"BTCUSD","markPrice":"12077.01343750","indexPrice":"10979.10312500","estimatedSettlePrice":"10981.74168236","lastFundingRate":"","interestRate":"","nextFundingTime":0,"time":1596094042000}]"#).unwrap();
            let expected_response : Vec<models::IndexPriceAndMarkPriceResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::IndexPriceAndMarkPriceResponseInner>");

            let resp = client.index_price_and_mark_price(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn index_price_and_mark_price_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: true };

            let params = IndexPriceAndMarkPriceParams::builder().build().unwrap();

            match client.index_price_and_mark_price(params).await {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn index_price_kline_candlestick_data_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: false };

            let params = IndexPriceKlineCandlestickDataParams::builder("pair_example".to_string(),IndexPriceKlineCandlestickDataIntervalEnum::Interval1m,).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"[[1591256400000,"9653.69440000","9653.69640000","9651.38600000","9651.55200000","0",1591256459999,"0",60,"0","0","0"]]"#).unwrap();
            let expected_response : Vec<Vec<models::IndexPriceKlineCandlestickDataResponseItemInner>> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<Vec<models::IndexPriceKlineCandlestickDataResponseItemInner>>");

            let resp = client.index_price_kline_candlestick_data(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn index_price_kline_candlestick_data_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: false };

            let params = IndexPriceKlineCandlestickDataParams::builder("pair_example".to_string(),IndexPriceKlineCandlestickDataIntervalEnum::Interval1m,).start_time(1623319461670).end_time(1641782889000).limit(100).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"[[1591256400000,"9653.69440000","9653.69640000","9651.38600000","9651.55200000","0",1591256459999,"0",60,"0","0","0"]]"#).unwrap();
            let expected_response : Vec<Vec<models::IndexPriceKlineCandlestickDataResponseItemInner>> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<Vec<models::IndexPriceKlineCandlestickDataResponseItemInner>>");

            let resp = client.index_price_kline_candlestick_data(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn index_price_kline_candlestick_data_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: true };

            let params = IndexPriceKlineCandlestickDataParams::builder(
                "pair_example".to_string(),
                IndexPriceKlineCandlestickDataIntervalEnum::Interval1m,
            )
            .build()
            .unwrap();

            match client.index_price_kline_candlestick_data(params).await {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn kline_candlestick_data_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: false };

            let params = KlineCandlestickDataParams::builder("symbol_example".to_string(),KlineCandlestickDataIntervalEnum::Interval1m,).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"[[1591258320000,"9640.7","9642.4","9640.6","9642.0","206",1591258379999,"2.13660389",48,"119","1.23424865","0"]]"#).unwrap();
            let expected_response : Vec<Vec<models::ContinuousContractKlineCandlestickDataResponseItemInner>> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<Vec<models::ContinuousContractKlineCandlestickDataResponseItemInner>>");

            let resp = client.kline_candlestick_data(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn kline_candlestick_data_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: false };

            let params = KlineCandlestickDataParams::builder("symbol_example".to_string(),KlineCandlestickDataIntervalEnum::Interval1m,).start_time(1623319461670).end_time(1641782889000).limit(100).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"[[1591258320000,"9640.7","9642.4","9640.6","9642.0","206",1591258379999,"2.13660389",48,"119","1.23424865","0"]]"#).unwrap();
            let expected_response : Vec<Vec<models::ContinuousContractKlineCandlestickDataResponseItemInner>> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<Vec<models::ContinuousContractKlineCandlestickDataResponseItemInner>>");

            let resp = client.kline_candlestick_data(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn kline_candlestick_data_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: true };

            let params = KlineCandlestickDataParams::builder(
                "symbol_example".to_string(),
                KlineCandlestickDataIntervalEnum::Interval1m,
            )
            .build()
            .unwrap();

            match client.kline_candlestick_data(params).await {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn long_short_ratio_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: false };

            let params = LongShortRatioParams::builder("pair_example".to_string(),LongShortRatioPeriodEnum::Period5m,).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"[{"pair":"BTCUSD","longShortRatio":"0.1960","longAccount":"0.6622","shortAccount":"0.3378","timestamp":1583139600000},{"pair":"BTCUSD","longShortRatio":"1.9559","longAccount":"0.6617","shortAccount":"0.3382","timestamp":1583139900000}]"#).unwrap();
            let expected_response : Vec<models::LongShortRatioResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::LongShortRatioResponseInner>");

            let resp = client.long_short_ratio(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn long_short_ratio_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: false };

            let params = LongShortRatioParams::builder("pair_example".to_string(),LongShortRatioPeriodEnum::Period5m,).limit(100).start_time(1623319461670).end_time(1641782889000).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"[{"pair":"BTCUSD","longShortRatio":"0.1960","longAccount":"0.6622","shortAccount":"0.3378","timestamp":1583139600000},{"pair":"BTCUSD","longShortRatio":"1.9559","longAccount":"0.6617","shortAccount":"0.3382","timestamp":1583139900000}]"#).unwrap();
            let expected_response : Vec<models::LongShortRatioResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::LongShortRatioResponseInner>");

            let resp = client.long_short_ratio(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn long_short_ratio_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: true };

            let params = LongShortRatioParams::builder(
                "pair_example".to_string(),
                LongShortRatioPeriodEnum::Period5m,
            )
            .build()
            .unwrap();

            match client.long_short_ratio(params).await {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn mark_price_kline_candlestick_data_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: false };

            let params = MarkPriceKlineCandlestickDataParams::builder("symbol_example".to_string(),MarkPriceKlineCandlestickDataIntervalEnum::Interval1m,).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"[[1591256460000,"9653.29201333","9654.56401333","9653.07367333","9653.07367333","0",1591256519999,"0",60,"0","0","0"]]"#).unwrap();
            let expected_response : Vec<Vec<models::MarkPriceKlineCandlestickDataResponseItemInner>> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<Vec<models::MarkPriceKlineCandlestickDataResponseItemInner>>");

            let resp = client.mark_price_kline_candlestick_data(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn mark_price_kline_candlestick_data_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: false };

            let params = MarkPriceKlineCandlestickDataParams::builder("symbol_example".to_string(),MarkPriceKlineCandlestickDataIntervalEnum::Interval1m,).start_time(1623319461670).end_time(1641782889000).limit(100).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"[[1591256460000,"9653.29201333","9654.56401333","9653.07367333","9653.07367333","0",1591256519999,"0",60,"0","0","0"]]"#).unwrap();
            let expected_response : Vec<Vec<models::MarkPriceKlineCandlestickDataResponseItemInner>> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<Vec<models::MarkPriceKlineCandlestickDataResponseItemInner>>");

            let resp = client.mark_price_kline_candlestick_data(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn mark_price_kline_candlestick_data_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: true };

            let params = MarkPriceKlineCandlestickDataParams::builder(
                "symbol_example".to_string(),
                MarkPriceKlineCandlestickDataIntervalEnum::Interval1m,
            )
            .build()
            .unwrap();

            match client.mark_price_kline_candlestick_data(params).await {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn old_trades_lookup_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: false };

            let params = OldTradesLookupParams::builder("symbol_example".to_string(),).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"[{"id":595103,"price":"9642.2","qty":"1","baseQty":"0.01037108","time":1499865549590,"isBuyerMaker":true}]"#).unwrap();
            let expected_response : Vec<models::OldTradesLookupResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::OldTradesLookupResponseInner>");

            let resp = client.old_trades_lookup(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn old_trades_lookup_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: false };

            let params = OldTradesLookupParams::builder("symbol_example".to_string(),).limit(100).from_id(1).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"[{"id":595103,"price":"9642.2","qty":"1","baseQty":"0.01037108","time":1499865549590,"isBuyerMaker":true}]"#).unwrap();
            let expected_response : Vec<models::OldTradesLookupResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::OldTradesLookupResponseInner>");

            let resp = client.old_trades_lookup(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn old_trades_lookup_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: true };

            let params = OldTradesLookupParams::builder("symbol_example".to_string())
                .build()
                .unwrap();

            match client.old_trades_lookup(params).await {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn open_interest_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: false };

            let params = OpenInterestParams::builder("symbol_example".to_string()).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"{"symbol":"BTCUSD_200626","pair":"BTCUSD","openInterest":"15004","contractType":"CURRENT_QUARTER","time":1591261042378}"#).unwrap();
            let expected_response : models::OpenInterestResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::OpenInterestResponse");

            let resp = client.open_interest(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn open_interest_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: false };

            let params = OpenInterestParams::builder("symbol_example".to_string()).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"{"symbol":"BTCUSD_200626","pair":"BTCUSD","openInterest":"15004","contractType":"CURRENT_QUARTER","time":1591261042378}"#).unwrap();
            let expected_response : models::OpenInterestResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::OpenInterestResponse");

            let resp = client.open_interest(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn open_interest_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: true };

            let params = OpenInterestParams::builder("symbol_example".to_string())
                .build()
                .unwrap();

            match client.open_interest(params).await {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn open_interest_statistics_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: false };

            let params = OpenInterestStatisticsParams::builder("pair_example".to_string(),OpenInterestStatisticsContractTypeEnum::Perpetual,OpenInterestStatisticsPeriodEnum::Period5m,).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"[{"pair":"BTCUSD","contractType":"CURRENT_QUARTER","sumOpenInterest":"20403","sumOpenInterestValue":"176196512.23400000","timestamp":1591261042378},{"pair":"BTCUSD","contractType":"CURRENT_QUARTER","sumOpenInterest":"20401","sumOpenInterestValue":"176178704.98700000","timestamp":1583128200000}]"#).unwrap();
            let expected_response : Vec<models::OpenInterestStatisticsResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::OpenInterestStatisticsResponseInner>");

            let resp = client.open_interest_statistics(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn open_interest_statistics_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: false };

            let params = OpenInterestStatisticsParams::builder("pair_example".to_string(),OpenInterestStatisticsContractTypeEnum::Perpetual,OpenInterestStatisticsPeriodEnum::Period5m,).limit(100).start_time(1623319461670).end_time(1641782889000).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"[{"pair":"BTCUSD","contractType":"CURRENT_QUARTER","sumOpenInterest":"20403","sumOpenInterestValue":"176196512.23400000","timestamp":1591261042378},{"pair":"BTCUSD","contractType":"CURRENT_QUARTER","sumOpenInterest":"20401","sumOpenInterestValue":"176178704.98700000","timestamp":1583128200000}]"#).unwrap();
            let expected_response : Vec<models::OpenInterestStatisticsResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::OpenInterestStatisticsResponseInner>");

            let resp = client.open_interest_statistics(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn open_interest_statistics_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: true };

            let params = OpenInterestStatisticsParams::builder(
                "pair_example".to_string(),
                OpenInterestStatisticsContractTypeEnum::Perpetual,
                OpenInterestStatisticsPeriodEnum::Period5m,
            )
            .build()
            .unwrap();

            match client.open_interest_statistics(params).await {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn order_book_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: false };

            let params = OrderBookParams::builder("symbol_example".to_string(),).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"{"lastUpdateId":16769853,"symbol":"BTCUSD_PERP","pair":"BTCUSD","E":1591250106370,"T":1591250106368,"bids":[["9638.0","431"]],"asks":[["9638.2","12"]]}"#).unwrap();
            let expected_response : models::OrderBookResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::OrderBookResponse");

            let resp = client.order_book(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn order_book_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: false };

            let params = OrderBookParams::builder("symbol_example".to_string(),).limit(100).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"{"lastUpdateId":16769853,"symbol":"BTCUSD_PERP","pair":"BTCUSD","E":1591250106370,"T":1591250106368,"bids":[["9638.0","431"]],"asks":[["9638.2","12"]]}"#).unwrap();
            let expected_response : models::OrderBookResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::OrderBookResponse");

            let resp = client.order_book(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn order_book_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: true };

            let params = OrderBookParams::builder("symbol_example".to_string())
                .build()
                .unwrap();

            match client.order_book(params).await {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn premium_index_kline_data_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: false };

            let params = PremiumIndexKlineDataParams::builder("symbol_example".to_string(),PremiumIndexKlineDataIntervalEnum::Interval1m,).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"[[1691603820000,"-0.00042931","-0.00023641","-0.00059406","-0.00043659","0",1691603879999,"0",12,"0","0","0"]]"#).unwrap();
            let expected_response : Vec<Vec<models::PremiumIndexKlineDataResponseItemInner>> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<Vec<models::PremiumIndexKlineDataResponseItemInner>>");

            let resp = client.premium_index_kline_data(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn premium_index_kline_data_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: false };

            let params = PremiumIndexKlineDataParams::builder("symbol_example".to_string(),PremiumIndexKlineDataIntervalEnum::Interval1m,).start_time(1623319461670).end_time(1641782889000).limit(100).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"[[1691603820000,"-0.00042931","-0.00023641","-0.00059406","-0.00043659","0",1691603879999,"0",12,"0","0","0"]]"#).unwrap();
            let expected_response : Vec<Vec<models::PremiumIndexKlineDataResponseItemInner>> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<Vec<models::PremiumIndexKlineDataResponseItemInner>>");

            let resp = client.premium_index_kline_data(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn premium_index_kline_data_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: true };

            let params = PremiumIndexKlineDataParams::builder(
                "symbol_example".to_string(),
                PremiumIndexKlineDataIntervalEnum::Interval1m,
            )
            .build()
            .unwrap();

            match client.premium_index_kline_data(params).await {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn query_index_price_constituents_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: false };

            let params = QueryIndexPriceConstituentsParams::builder("symbol_example".to_string()).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"{"symbol":"BTCUSD","time":1697422647853,"constituents":[{"exchange":"bitstamp","symbol":"btcusd"},{"exchange":"coinbase","symbol":"BTC-USD"},{"exchange":"kraken","symbol":"XBT/USD"},{"exchange":"binance_cross","symbol":"BTCUSDC*index(USDCUSD)"}]}"#).unwrap();
            let expected_response : models::QueryIndexPriceConstituentsResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::QueryIndexPriceConstituentsResponse");

            let resp = client.query_index_price_constituents(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn query_index_price_constituents_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: false };

            let params = QueryIndexPriceConstituentsParams::builder("symbol_example".to_string()).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"{"symbol":"BTCUSD","time":1697422647853,"constituents":[{"exchange":"bitstamp","symbol":"btcusd"},{"exchange":"coinbase","symbol":"BTC-USD"},{"exchange":"kraken","symbol":"XBT/USD"},{"exchange":"binance_cross","symbol":"BTCUSDC*index(USDCUSD)"}]}"#).unwrap();
            let expected_response : models::QueryIndexPriceConstituentsResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::QueryIndexPriceConstituentsResponse");

            let resp = client.query_index_price_constituents(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn query_index_price_constituents_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: true };

            let params = QueryIndexPriceConstituentsParams::builder("symbol_example".to_string())
                .build()
                .unwrap();

            match client.query_index_price_constituents(params).await {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn recent_trades_list_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: false };

            let params = RecentTradesListParams::builder("symbol_example".to_string(),).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"[{"id":28457,"price":"9635.0","qty":"1","baseQty":"0.01037883","time":1591250192508,"isBuyerMaker":true}]"#).unwrap();
            let expected_response : Vec<models::RecentTradesListResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::RecentTradesListResponseInner>");

            let resp = client.recent_trades_list(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn recent_trades_list_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: false };

            let params = RecentTradesListParams::builder("symbol_example".to_string(),).limit(100).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"[{"id":28457,"price":"9635.0","qty":"1","baseQty":"0.01037883","time":1591250192508,"isBuyerMaker":true}]"#).unwrap();
            let expected_response : Vec<models::RecentTradesListResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::RecentTradesListResponseInner>");

            let resp = client.recent_trades_list(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn recent_trades_list_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: true };

            let params = RecentTradesListParams::builder("symbol_example".to_string())
                .build()
                .unwrap();

            match client.recent_trades_list(params).await {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn symbol_order_book_ticker_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: false };

            let params = SymbolOrderBookTickerParams::builder().build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"[{"lastUpdateId":1027024,"symbol":"BTCUSD_200626","pair":"BTCUSD","bidPrice":"9650.1","bidQty":"16","askPrice":"9650.3","askQty":"7","time":1591257300345}]"#).unwrap();
            let expected_response : Vec<models::SymbolOrderBookTickerResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::SymbolOrderBookTickerResponseInner>");

            let resp = client.symbol_order_book_ticker(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn symbol_order_book_ticker_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: false };

            let params = SymbolOrderBookTickerParams::builder().symbol("symbol_example".to_string()).pair("pair_example".to_string()).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"[{"lastUpdateId":1027024,"symbol":"BTCUSD_200626","pair":"BTCUSD","bidPrice":"9650.1","bidQty":"16","askPrice":"9650.3","askQty":"7","time":1591257300345}]"#).unwrap();
            let expected_response : Vec<models::SymbolOrderBookTickerResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::SymbolOrderBookTickerResponseInner>");

            let resp = client.symbol_order_book_ticker(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn symbol_order_book_ticker_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: true };

            let params = SymbolOrderBookTickerParams::builder().build().unwrap();

            match client.symbol_order_book_ticker(params).await {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn symbol_price_ticker_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: false };

            let params = SymbolPriceTickerParams::builder().build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"[{"symbol":"BTCUSD_200626","ps":"9647.8","price":"9647.8","time":1591257246176}]"#).unwrap();
            let expected_response : Vec<models::SymbolPriceTickerResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::SymbolPriceTickerResponseInner>");

            let resp = client.symbol_price_ticker(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn symbol_price_ticker_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: false };

            let params = SymbolPriceTickerParams::builder().symbol("symbol_example".to_string()).pair("pair_example".to_string()).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"[{"symbol":"BTCUSD_200626","ps":"9647.8","price":"9647.8","time":1591257246176}]"#).unwrap();
            let expected_response : Vec<models::SymbolPriceTickerResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::SymbolPriceTickerResponseInner>");

            let resp = client.symbol_price_ticker(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn symbol_price_ticker_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: true };

            let params = SymbolPriceTickerParams::builder().build().unwrap();

            match client.symbol_price_ticker(params).await {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn taker_buy_sell_volume_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: false };

            let params = TakerBuySellVolumeParams::builder("pair_example".to_string(),TakerBuySellVolumeContractTypeEnum::Perpetual,TakerBuySellVolumePeriodEnum::Period5m,).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"[{"pair":"BTCUSD","contractType":"CURRENT_QUARTER","takerBuyVol":"387","takerSellVol":"248","takerBuyVolValue":"2342.1220","takerSellVolValue":"4213.9800","timestamp":1591261042378},{"pair":"BTCUSD","contractType":"CURRENT_QUARTER","takerBuyVol":"234","takerSellVol":"121","takerBuyVolValue":"4563.1320","takerSellVolValue":"3313.3940","timestamp":1585615200000}]"#).unwrap();
            let expected_response : Vec<models::TakerBuySellVolumeResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::TakerBuySellVolumeResponseInner>");

            let resp = client.taker_buy_sell_volume(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn taker_buy_sell_volume_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: false };

            let params = TakerBuySellVolumeParams::builder("pair_example".to_string(),TakerBuySellVolumeContractTypeEnum::Perpetual,TakerBuySellVolumePeriodEnum::Period5m,).limit(100).start_time(1623319461670).end_time(1641782889000).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"[{"pair":"BTCUSD","contractType":"CURRENT_QUARTER","takerBuyVol":"387","takerSellVol":"248","takerBuyVolValue":"2342.1220","takerSellVolValue":"4213.9800","timestamp":1591261042378},{"pair":"BTCUSD","contractType":"CURRENT_QUARTER","takerBuyVol":"234","takerSellVol":"121","takerBuyVolValue":"4563.1320","takerSellVolValue":"3313.3940","timestamp":1585615200000}]"#).unwrap();
            let expected_response : Vec<models::TakerBuySellVolumeResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::TakerBuySellVolumeResponseInner>");

            let resp = client.taker_buy_sell_volume(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn taker_buy_sell_volume_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: true };

            let params = TakerBuySellVolumeParams::builder(
                "pair_example".to_string(),
                TakerBuySellVolumeContractTypeEnum::Perpetual,
                TakerBuySellVolumePeriodEnum::Period5m,
            )
            .build()
            .unwrap();

            match client.taker_buy_sell_volume(params).await {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn test_connectivity_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: false };

            let expected_response = Value::Null;

            let resp = client
                .test_connectivity()
                .await
                .expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn test_connectivity_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: false };

            let expected_response = Value::Null;

            let resp = client
                .test_connectivity()
                .await
                .expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn test_connectivity_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: true };

            match client.test_connectivity().await {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn ticker24hr_price_change_statistics_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: false };

            let params = Ticker24hrPriceChangeStatisticsParams::builder().build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"[{"symbol":"BTCUSD_200925","pair":"BTCUSD","priceChange":"136.6","priceChangePercent":"1.436","weightedAvgPrice":"9547.3","lastPrice":"9651.6","lastQty":"1","openPrice":"9515.0","highPrice":"9687.0","lowPrice":"9499.5","volume":"494109","baseVolume":"5192.94797687","openTime":1591170300000,"closeTime":1591256718418,"firstId":600507,"lastId":697803,"count":97297}]"#).unwrap();
            let expected_response : Vec<models::Ticker24hrPriceChangeStatisticsResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::Ticker24hrPriceChangeStatisticsResponseInner>");

            let resp = client.ticker24hr_price_change_statistics(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn ticker24hr_price_change_statistics_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: false };

            let params = Ticker24hrPriceChangeStatisticsParams::builder().symbol("symbol_example".to_string()).pair("pair_example".to_string()).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"[{"symbol":"BTCUSD_200925","pair":"BTCUSD","priceChange":"136.6","priceChangePercent":"1.436","weightedAvgPrice":"9547.3","lastPrice":"9651.6","lastQty":"1","openPrice":"9515.0","highPrice":"9687.0","lowPrice":"9499.5","volume":"494109","baseVolume":"5192.94797687","openTime":1591170300000,"closeTime":1591256718418,"firstId":600507,"lastId":697803,"count":97297}]"#).unwrap();
            let expected_response : Vec<models::Ticker24hrPriceChangeStatisticsResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::Ticker24hrPriceChangeStatisticsResponseInner>");

            let resp = client.ticker24hr_price_change_statistics(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn ticker24hr_price_change_statistics_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: true };

            let params = Ticker24hrPriceChangeStatisticsParams::builder()
                .build()
                .unwrap();

            match client.ticker24hr_price_change_statistics(params).await {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn top_trader_long_short_ratio_accounts_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: false };

            let params = TopTraderLongShortRatioAccountsParams::builder("symbol_example".to_string(),TopTraderLongShortRatioAccountsPeriodEnum::Period5m,).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"[{"pair":"BTCUSD","longShortRatio":"1.8105","longAccount":"0.6442","shortAccount":"0.3558","timestamp":1591261042378},{"pair":"BTCUSD","longShortRatio":"1.1110","longAccount":"0.5263","shortAccount":"0.4737","timestamp":1592870400000}]"#).unwrap();
            let expected_response : Vec<models::TopTraderLongShortRatioAccountsResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::TopTraderLongShortRatioAccountsResponseInner>");

            let resp = client.top_trader_long_short_ratio_accounts(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn top_trader_long_short_ratio_accounts_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: false };

            let params = TopTraderLongShortRatioAccountsParams::builder("symbol_example".to_string(),TopTraderLongShortRatioAccountsPeriodEnum::Period5m,).limit(100).start_time(1623319461670).end_time(1641782889000).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"[{"pair":"BTCUSD","longShortRatio":"1.8105","longAccount":"0.6442","shortAccount":"0.3558","timestamp":1591261042378},{"pair":"BTCUSD","longShortRatio":"1.1110","longAccount":"0.5263","shortAccount":"0.4737","timestamp":1592870400000}]"#).unwrap();
            let expected_response : Vec<models::TopTraderLongShortRatioAccountsResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::TopTraderLongShortRatioAccountsResponseInner>");

            let resp = client.top_trader_long_short_ratio_accounts(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn top_trader_long_short_ratio_accounts_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: true };

            let params = TopTraderLongShortRatioAccountsParams::builder(
                "symbol_example".to_string(),
                TopTraderLongShortRatioAccountsPeriodEnum::Period5m,
            )
            .build()
            .unwrap();

            match client.top_trader_long_short_ratio_accounts(params).await {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn top_trader_long_short_ratio_positions_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: false };

            let params = TopTraderLongShortRatioPositionsParams::builder("pair_example".to_string(),TopTraderLongShortRatioPositionsPeriodEnum::Period5m,).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"[{"pair":"BTCUSD","longShortRatio":"0.7869","longPosition":"0.6442","shortPosition":"0.4404","timestamp":1592870400000},{"pair":"BTCUSD","longShortRatio":"1.1231","longPosition":"0.2363","shortPosition":"0.4537","timestamp":1592956800000}]"#).unwrap();
            let expected_response : Vec<models::TopTraderLongShortRatioPositionsResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::TopTraderLongShortRatioPositionsResponseInner>");

            let resp = client.top_trader_long_short_ratio_positions(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn top_trader_long_short_ratio_positions_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: false };

            let params = TopTraderLongShortRatioPositionsParams::builder("pair_example".to_string(),TopTraderLongShortRatioPositionsPeriodEnum::Period5m,).limit(100).start_time(1623319461670).end_time(1641782889000).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"[{"pair":"BTCUSD","longShortRatio":"0.7869","longPosition":"0.6442","shortPosition":"0.4404","timestamp":1592870400000},{"pair":"BTCUSD","longShortRatio":"1.1231","longPosition":"0.2363","shortPosition":"0.4537","timestamp":1592956800000}]"#).unwrap();
            let expected_response : Vec<models::TopTraderLongShortRatioPositionsResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::TopTraderLongShortRatioPositionsResponseInner>");

            let resp = client.top_trader_long_short_ratio_positions(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn top_trader_long_short_ratio_positions_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockMarketDataApiClient { force_error: true };

            let params = TopTraderLongShortRatioPositionsParams::builder(
                "pair_example".to_string(),
                TopTraderLongShortRatioPositionsPeriodEnum::Period5m,
            )
            .build()
            .unwrap();

            match client.top_trader_long_short_ratio_positions(params).await {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }
}
