chapaty 0.1.4

A software to backtest trading strategies.
Documentation
use crate::{
    converter::pnl_to_report::{as_equity_curve, PnLToReportRequestBuilder},
    enums::markets::MarketKind,
    equity_curve::{EquityCurves, EquityCurvesReport},
    lazy_frame_operations::trait_extensions::{MyLazyFrameOperations, MyLazyFrameVecOperations},
    performance_report::PerformanceReports,
    trade_breakdown_report::TradeBreakdownReports,
};
use polars::prelude::{DataFrame, IntoLazy, LazyFrame};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;

use super::pnl_report::PnLReports;

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct PnLStatement {
    pub strategy_name: String,
    pub markets: Vec<MarketKind>,
    pub pnl_data: HashMap<MarketKind, PnLReports>,
}

impl PnLStatement {
    pub fn save_as_csv(&self, file_name: &str) {
        self.pnl_data
            .iter()
            .for_each(|(_, data)| data.save_as_csv(file_name))
    }

    pub fn agg_markets(&self) -> HashMap<u32, DataFrame> {
        let years: &Vec<u32> = self.pnl_data[&self.markets[0]].years.as_ref();
        years
            .iter()
            .map(|year| (*year, self.get_agg_pnl_report_in_year(year)))
            .collect()
    }

    fn get_agg_pnl_report_in_year(&self, year: &u32) -> DataFrame {
        self.pnl_data
            .values()
            .map(|pnl_reports| pnl_reports.reports.get(year).unwrap().clone().lazy())
            .collect::<Vec<LazyFrame>>()
            .concatenate_to_lazy_frame()
            .sort_by_date()
            .collect()
            .unwrap()
    }

    pub fn get_years(&self) -> Vec<u32> {
        self.pnl_data[&self.markets[0]].years.clone()
    }

    pub fn compute_trade_breakdown_report(&self) -> TradeBreakdownReports {
        let request_builder = PnLToReportRequestBuilder::new()
            .is_agg_markets(false)
            .is_agg_years(false);
        let trade_breakdown_reports: HashMap<MarketKind, DataFrame> = self
            .pnl_data
            .iter()
            .map(|(market, pnl_reports)| {
                (
                    *market,
                    pnl_reports
                        .reports
                        .iter()
                        .map(|(year, pnl_report)| {
                            request_builder
                                .clone()
                                .with_pnl(pnl_report.clone())
                                .with_market(*market)
                                .with_strategy(self.strategy_name.clone())
                                .with_year(*year)
                                .build()
                                .as_trade_breakdown_df()
                        })
                        .map(|df| df.lazy())
                        .collect::<Vec<LazyFrame>>()
                        .concatenate_to_data_frame()
                        .with_row_count("#", Some(1))
                        .unwrap(),
                )
            })
            .collect();

        TradeBreakdownReports {
            markets: self.markets.clone(),
            reports: trade_breakdown_reports,
        }
    }
    pub fn compute_performance_report(&self) -> PerformanceReports {
        let request_builder = PnLToReportRequestBuilder::new()
            .is_agg_markets(false)
            .is_agg_years(false);
        let trade_breakdown_reports: HashMap<MarketKind, DataFrame> = self
            .pnl_data
            .iter()
            .map(|(market, pnl_reports)| {
                (
                    *market,
                    pnl_reports
                        .reports
                        .iter()
                        .map(|(year, pnl_report)| {
                            request_builder
                                .clone()
                                .with_pnl(pnl_report.clone())
                                .with_market(*market)
                                .with_strategy(self.strategy_name.clone())
                                .with_year(*year)
                                .build()
                                .as_performance_report_df()
                        })
                        .map(|df| df.lazy())
                        .collect::<Vec<LazyFrame>>()
                        .concatenate_to_data_frame()
                        .with_row_count("#", Some(1))
                        .unwrap(),
                )
            })
            .collect();

        PerformanceReports {
            markets: self.markets.clone(),
            reports: trade_breakdown_reports,
        }
    }

    pub fn compute_equity_curves(&self) -> EquityCurvesReport {
        let equity_curves = self
            .pnl_data
            .iter()
            .map(|(market, pnl_reports)| {
                let curves = pnl_reports
                    .reports
                    .iter()
                    .map(|(year, pnl_report)| (*year, as_equity_curve(&pnl_report, false)))
                    .collect();
                (
                    *market,
                    EquityCurves {
                        market: *market,
                        years: pnl_reports.years.clone(),
                        curves,
                    },
                )
            })
            .collect();

        EquityCurvesReport {
            markets: self.markets.clone(),
            curves: equity_curves,
        }
    }
}