import pandas as pd
from utils import filter_weekend, config, dict_remove
from datas import navs
from dateutil.relativedelta import relativedelta
from empyrical import sortino_ratio

optimize_config = config['fund_pool']['fund_optimize'] if 'fund_pool' in config and 'fund_optimize' in config['fund_pool'] else {}
sortino_config = [{**x, 'name': [f"sortino_{y[1]}_{y[0]}" for y in x.items() if y[0] != 'weight'][0]} for x in optimize_config['sortino_weight']] \
    if 'sortino_weight' in optimize_config else []


def find_optimize(fund_ids, day):
    if not sortino_config:
        raise NameError(f"find optimize, but not found sortino config.")
    start = filter_weekend(sorted([day - relativedelta(days=1, **dict_remove(x, ('weight', 'name'))) for x in sortino_config])[0])
    fund_navs = pd.DataFrame(navs.get_navs(fund_id=tuple(fund_ids), min_date=start, max_date=day))
    fund_navs.sort_values('nav_date', inplace=True)
    fund_navs = fund_navs.pivot_table(index='nav_date', columns='fund_id', values='nav_cal')
    fund_navs.fillna(method='ffill', inplace=True)
    day_income = round(fund_navs.pct_change(), 4)
    sortino = pd.DataFrame()
    for item in sortino_config:
        delta_kwargs = item.copy()
        del delta_kwargs['weight'], delta_kwargs['name']
        ratio = dict(sortino_ratio(day_income.truncate(before=(day - relativedelta(**delta_kwargs)))))
        sortino = pd.concat([sortino, pd.DataFrame([ratio], index=[item['name']])])
    sortino = sortino.T
    sortino['score'] = sortino.apply(lambda r: sum([x['weight'] * r[x['name']] for x in sortino_config]), axis=1)
    sortino.sort_values('score', ascending=False, inplace=True)
    return day_income.columns[sortino.index[0]]


def get_optimize_fund_pool(day):
    pass


if __name__ == '__main__':
    from datetime import date

    get_optimize_fund_pool(date.today())