import numpy as np
import pandas as pd

from strategies.mlp_accounting import net_returns
from tools.run_mlp_incumbent_audit import benchmark, ledger, overridden_metrics


def test_ledger_reconstructs_equity_and_includes_both_fees():
    frame=pd.DataFrame({'time':pd.date_range('2020-01-01',periods=5),'close':[100.,110.,120.,100.,105.],
                        'position':[1,1,0,1,1],'execute_entry':[True,False,False,True,False],
                        'execute_exit':[False,False,True,False,False]})
    result=ledger(frame)
    expected=(1+.1-.005)*(1+120/110-1-.005)-1
    assert np.isclose(result.iloc[0].net_return_pct,expected*100)
    assert np.isclose(result.initial_equity_pnl.sum(),np.prod(1+net_returns(frame))-1)
    assert result.iloc[-1]['open']
    assert result.iloc[-1].first_return_index==4


def test_benchmark_causal_and_entry_fee_delayed():
    frame=pd.DataFrame({'time':pd.date_range('2017-01-01',periods=600),'close':np.linspace(100,200,600)})
    whole=benchmark(frame,'trend_200_calendar_days')
    prefix=benchmark(frame.iloc[:450],'trend_200_calendar_days')
    pd.testing.assert_frame_equal(whole.iloc[:450],prefix)
    buy=benchmark(frame,'buy_hold')
    entry=np.flatnonzero(buy.execute_entry)[0]
    assert net_returns(buy).iloc[entry]==0
    assert np.isclose(net_returns(buy).iloc[entry+1],frame.close.iloc[entry+1]/frame.close.iloc[entry]-1-.005)


def test_zero_return_diagnostic_keeps_calendar_and_counts():
    frame=pd.DataFrame({'time':pd.date_range('2020-01-01',periods=5),'close':[100,90,80,90,100],
                        'position':[1,1,1,1,1],'execute_entry':[True,False,False,False,False],
                        'execute_exit':[False]*5})
    result=overridden_metrics(frame,np.zeros(5),'2020-01-01','2020-01-05')
    assert result['pnl_pct']==0
    assert result['entries']==1
    assert np.isclose(result['years'],5/365.25)
