use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use crate::{
KiteConnect,
constants::{Endpoints, app_constants::*},
models::{KiteConnectError, time},
};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MTFHolding {
pub quantity: i32,
pub used_quantity: i32,
pub average_price: f64,
pub value: f64,
pub initial_margin: f64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Holding {
pub tradingsymbol: String,
pub exchange: String,
pub instrument_token: u32,
pub isin: String,
pub product: String,
pub price: f64,
pub used_quantity: i32,
pub quantity: i32,
pub t1_quantity: i32,
pub realised_quantity: i32,
pub authorised_quantity: i32,
pub authorised_date: time::Time,
pub opening_quantity: i32,
pub collateral_quantity: i32,
pub collateral_type: String,
pub discrepancy: bool,
pub average_price: f64,
pub last_price: f64,
pub close_price: f64,
pub pnl: f64,
pub day_change: f64,
pub day_change_percentage: f64,
pub mtf: MTFHolding,
}
pub type Holdings = Vec<Holding>;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Position {
pub tradingsymbol: String,
pub exchange: String,
pub instrument_token: u32,
pub product: String,
pub quantity: i32,
pub overnight_quantity: i32,
pub multiplier: f64,
pub average_price: f64,
pub close_price: f64,
pub last_price: f64,
pub value: f64,
pub pnl: f64,
pub m2m: f64,
pub unrealised: f64,
pub realised: f64,
pub buy_quantity: i32,
pub buy_price: f64,
pub buy_value: f64,
pub buy_m2m: f64,
pub sell_quantity: i32,
pub sell_price: f64,
pub sell_value: f64,
pub sell_m2m: f64,
pub day_buy_quantity: i32,
pub day_buy_price: f64,
pub day_buy_value: f64,
pub day_sell_quantity: i32,
pub day_sell_price: f64,
pub day_sell_value: f64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Positions {
pub net: Vec<Position>,
pub day: Vec<Position>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ConvertPositionParams {
pub exchange: String,
pub tradingsymbol: String,
pub old_product: String,
pub new_product: String,
pub position_type: String,
pub transaction_type: String,
pub quantity: i32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AuctionInstrument {
pub tradingsymbol: String,
pub exchange: String,
pub instrument_token: u32,
pub isin: String,
pub product: String,
pub price: f64,
pub quantity: i32,
pub t1_quantity: i32,
pub realised_quantity: i32,
pub authorised_quantity: i32,
pub authorised_date: String,
pub opening_quantity: i32,
pub collateral_quantity: i32,
pub collateral_type: String,
pub discrepancy: bool,
pub average_price: f64,
pub last_price: f64,
pub close_price: f64,
pub pnl: f64,
pub day_change: f64,
pub day_change_percentage: f64,
pub auction_number: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HoldingsAuthInstruments {
pub isin: String,
pub quantity: f64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HoldingAuthParams {
#[serde(rename = "type")]
pub auth_type: String,
pub transfer_type: String,
pub exec_date: String,
pub instruments: Option<Vec<HoldingsAuthInstruments>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HoldingsAuthResp {
pub request_id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub redirect_url: Option<String>,
}
impl KiteConnect {
pub async fn get_holdings(&self) -> Result<Holdings, KiteConnectError> {
self.get(Endpoints::GET_HOLDINGS).await
}
pub async fn get_auction_instruments(
&self,
) -> Result<Vec<AuctionInstrument>, KiteConnectError> {
self.get(Endpoints::AUCTION_INSTRUMENTS).await
}
pub async fn get_positions(&self) -> Result<Positions, KiteConnectError> {
self.get(Endpoints::GET_POSITIONS).await
}
pub async fn convert_position(
&self,
position_params: ConvertPositionParams,
) -> Result<bool, KiteConnectError> {
match self
.put_form::<serde_json::Value, _>(Endpoints::CONVERT_POSITION, position_params)
.await
{
Ok(_) => Ok(true),
Err(e) => Err(e),
}
}
pub async fn initiate_holdings_auth(
&self,
auth_params: HoldingAuthParams,
) -> Result<HoldingsAuthResp, KiteConnectError> {
let mut params = HashMap::new();
if !auth_params.auth_type.is_empty() {
params.insert("type".to_string(), auth_params.auth_type);
}
if !auth_params.transfer_type.is_empty() {
params.insert("transfer_type".to_string(), auth_params.transfer_type);
}
if !auth_params.exec_date.is_empty() {
params.insert("exec_date".to_string(), auth_params.exec_date);
}
if let Some(instruments) = auth_params.instruments {
for instrument in instruments {
params.insert("isin".to_string(), instrument.isin);
params.insert("quantity".to_string(), instrument.quantity.to_string());
}
}
let mut resp: HoldingsAuthResp = self
.post_form(Endpoints::INIT_HOLDINGS_AUTH, params)
.await?;
let login_url = format!(
"{}/connect/portfolio/authorise/holdings/{}/{}",
KITE_BASE_URL, &self.api_key, &resp.request_id
);
resp.redirect_url = Some(login_url);
Ok(resp)
}
}