qust 0.1.5

A crate for finance quantative reserach
Documentation
use crate::idct::ta::Ta;
use crate::prelude::TradingPeriod;
use crate::prelude::{Calc, CalcSave, CalcSaveWrapper, Pre};
use crate::trade::di::*;
use chrono::Timelike;
use qust_derive::*;
use qust_ds::prelude::*;

pub struct FData<'f, T, N> {
    pub data: &'f T,
    pub f: N,
}

fn _find_day_index(time_vec: &[dt]) -> vuz {
    let mut res = vec![0usize];
    for i in 1..time_vec.len() {
        if time_vec[i].date() != time_vec[i - 1].date() {
            res.push(i);
        }
    }
    res.push(time_vec.len());
    res
}
pub fn find_day_index_night_flat(time_vec: avdt) -> vuz {
    let mut res = vec![0usize; time_vec.len()];
    let hour_vec = time_vec.iter().map(|x| x.hour()).collect_vec();
    let end_range = 13..16;
    for i in 1..res.len() {
        if end_range.contains(&hour_vec[i - 1]) && !end_range.contains(&hour_vec[i]) {
            res[i] = res[i - 1] + 1;
        } else {
            res[i] = res[i - 1];
        }
    }
    res
}
pub fn find_day_index_night(time_vec: avdt) -> vuz {
    let mut res = vec![0usize];
    let hour_vec = time_vec.iter().map(|x| x.hour()).collect_vec();
    let end_range = 13..16;
    for i in 1..time_vec.len() {
        if end_range.contains(&hour_vec[i - 1]) && !end_range.contains(&hour_vec[i]) {
            res.push(i);
        }
    }
    res.push(time_vec.len());
    res
}

#[ta_derive]
struct FindDayIndex(Pre);

impl CalcSave for FindDayIndex {
    type Output = vuz;
    fn calc_save(&self, di: &Di) -> Self::Output {
        self.0 .1.cut_index(di)
    }
}

pub(crate) fn find_day_index_night_pre(time_vec: &[dt]) -> vuz {
    let mut res = vec![0usize];
    let hour_vec = time_vec.map(|x| x.hour());
    let tt_vec = time_vec.map(|x| x.time());
    let end_range_light = 8..20;
    let end_range_night = 20..23;
    izip!(hour_vec.windows(2), tt_vec.windows(2))
        .enumerate()
        .for_each(|(i, (h, t))| {
            let (hour_pre, hour_now) = (h.first().unwrap(), h.last().unwrap());
            let is_in_light_pre = end_range_light.contains(hour_pre);
            let is_in_night_now = end_range_night.contains(hour_now);
            let is_in_cut = if is_in_light_pre && is_in_night_now {
                true
            } else {
                let time_pre = t.first().unwrap();
                let time_now = t.last().unwrap();
                let is_time_growing = time_pre > time_now;
                if is_in_light_pre && is_time_growing {
                    true
                } else {
                    let is_in_night_pre = end_range_night.contains(hour_pre);
                    is_in_night_pre && is_in_night_now && is_time_growing
                }
            };
            if is_in_cut {
                res.push(i + 1);
            }
        });
    res.push(time_vec.len());
    res
}

pub fn find_day_index_night_pro(time_vec: &[dt], di: &Di) -> vuz {
    let trading_period: TradingPeriod = di.pcon.ticker.into();
    match trading_period {
        TradingPeriod::LightNightMorn => find_day_index_night_pre(time_vec),
        _ => find_day_index_night_pre(time_vec),
    }
}

#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
pub enum Part {
    oos,
    ono,
}

impl Part {
    pub fn calc_part(&self, di: &Di, ta: Box<dyn Ta>) -> vv32 {
        let index_part = Pre(di.last_dcon(), self.clone())
            .pip(FindDayIndex)
            .pip(CalcSaveWrapper)
            .calc(di);
        let index_part = index_part.downcast_ref().unwrap();
        let data = ta.calc_di(di);
        let mut data_iter = self.cut_part(index_part, &data);
        let mut res_part = ta.calc_da(data_iter.next().unwrap(), di);
        let mut accu = init_a_matrix(data[0].len(), res_part.len());
        accu.vcat_other(&mut res_part);
        for data_part in data_iter {
            let mut res_part = ta.calc_da(data_part, di);
            accu.vcat_other(&mut res_part);
        }
        accu
    }
    fn cut_index(&self, di: &Di) -> vuz {
        match *self {
            Part::oos => {
                let time_vec = di.t();
                find_day_index_night_pro(&time_vec, di)
            }
            Part::ono => {
                vec![0, di.t().len()]
            }
        }
    }
    fn cut_part<'a>(
        &self,
        index_part: &'a vuz,
        data: &'a avv32,
    ) -> impl Iterator<Item = Vec<&'a [f32]>> {
        index_part.windows(2).map(|x| {
            data.iter()
                .map(|d| &d[*x.first().unwrap()..*x.last().unwrap()])
                .collect_vec()
        })
    }
}