import pandas as pd
import datetime
import talib
from backtesting import Strategy
from backtesting.lib import crossover
from backtesting import Backtest
import re
import warnings
warnings.filterwarnings('ignore')#警告文を表示させない

#%matplotlib inline

df = pd.read_csv('C:/Users/xi/MT5/in_dat/common.csv', index_col=0)
use_max = df.iat[0,0]
use = df.iat[0,1]
spread = df.iat[0,2]
use_data = df.iat[0,3]
if  use_data == 'short':
    data = df.iat[0,4]
if  use_data == 'long':
    data = df.iat[0,5]
max_weight = df.iat[0,6]
opt_factor = df.iat[0,7]
flag = 0
path_ohlcv = 'C:/Users/xi/MT5/in_dat/{}/OHLCV_{}_AROON.csv'
path_ohlcv = path_ohlcv.format(use_data,use_data)
path_opt = 'C:/Users/xi/MT5/out_dat/{}/opt/opt_AROON.csv'
path_opt = path_opt.format(use_data)
path_para = 'C:/Users/xi/MT5/out_dat/{}/para/para_AROON.csv'
path_para = path_para.format(use_data)

#インジケーターの計算を行う関数
def AROON(value1,value2,n):
    high = pd.Series(value1)
    low = pd.Series(value2)
    return talib.AROON(high, low, timeperiod=n)

def ATR(value1,value2,value3,n):
    high = pd.Series(value1)
    low = pd.Series(value2)
    close = pd.Series(value3)
    return talib.ATR(high, low, close, timeperiod=n)

# データの読み込み
while True:
    try:
        # データの読み込み
        #長期の場合OHLCVのPathだけ短期のPathにする(短期の方はそのまま)
        #最終行を取得---------
        lastRow = sum(1 for line in open(path_ohlcv)) - 2
        #最終行からuse_max行の行数を求める
        pickRow = [lastRow - line for line in range(use_max)]
        pickRow.reverse()
        df = pd.read_csv(path_ohlcv, header=None,skiprows=lambda x: x not in pickRow)
        df.columns = ['time','Open','High','Low','Close','Volume']
        df = df.drop(0)
        # timeの型変換
        # datetime型にする
        df = df.astype({'Open':float,'High':float,'Low':float,'Close':float,'Volume':float})
        df_first = df.tail(1)
        ohlcv_last = df_first.iat[0,0]
        ohlcv_last = pd.to_datetime(ohlcv_last)
        dt_now = datetime.datetime.now()
        dt_now = pd.to_datetime(dt_now)
        td = dt_now - ohlcv_last
        if data == '10S':
            if td.seconds < 30:
                flag = 1
                df["time"] = pd.to_datetime(df["time"])
                df = df.set_index('time')
            else:
                flag = 0
        if data == '30S':
            if td.seconds < 90:
                flag = 1
                df["time"] = pd.to_datetime(df["time"])
                df = df.set_index('time')
            else:
                flag = 0
        if data == '1T':
            if td.seconds < 180:
                flag = 1
                df["time"] = pd.to_datetime(df["time"])
                df = df.set_index('time')
            else:
                flag = 0
        if data == '3T':
            if td.seconds < 540:
                flag = 1
                df["time"] = pd.to_datetime(df["time"])
                df = df.set_index('time')
            else:
                flag = 0
        if data == '5T':
            if td.seconds < 900:
                flag = 1
                df["time"] = pd.to_datetime(df["time"])
                df = df.set_index('time')
            else:
                flag = 0
        if data == '10T':
            if td.seconds < 1800:
                flag = 1
                df["time"] = pd.to_datetime(df["time"])
                df = df.set_index('time')
            else:
                flag = 0
        if data == '15T':
            if td.seconds < 2700:
                flag = 1
                df["time"] = pd.to_datetime(df["time"])
                df = df.set_index('time')
            else:
                flag = 0
        
        if flag == 1:
            #----------------------
            #NaN回避
            nan_count = df.isnull().sum()
            nan_count_sum = 0
            for i in range(len(nan_count)):
                nan_count_sum = nan_count_sum + nan_count[i]
            #OHLCVにNaNが含まれてなかった場合のみ次へ
            if nan_count_sum == 0:
            
            #売買ルール
                class AROONt(Strategy):
                    n = 26
                    r = 14
                    a = 10
                    w = max_weight

                    def init(self):
                        self.aroondown, self.aroonup = self.I(AROON, self.data['High'], self.data['Low'], self.n)
                        self.atr = self.I(ATR, self.data['High'], self.data['Low'], self.data['Close'], self.r)
                    
                    def next(self):
                        if self.w >= self.atr * self.a >= 0.03:
                            if not self.position:
                                if (self.aroonup[-2] < self.aroondown[-2] and self.aroonup[-1] > self.aroondown[-1]): 
                                    self.buy(limit=self.data['Close'],tp = self.data['Close'] + (self.atr * self.a) + (spread * 0.01), sl = self.data['Close'] - (self.atr * self.a))
                                if (self.aroonup[-2] > self.aroondown[-2] and self.aroonup[-1] < self.aroondown[-1]):
                                    self.sell(limit=self.data['Close'], tp = self.data['Close'] - (self.atr * self.a) - (spread * 0.01), sl = self.data['Close'] + (self.atr * self.a))

                #読み込んだOHLCVデータの一部だけ使う(最新からuse分だけ)
                df_ = df.tail(use)

                #AROON最適化
                dt_now = datetime.datetime.now()
                print(dt_now)
                print("-----------------AROON-----------------")
                #Backtest(使うOHLCVデータ,使う売買ルールのクラス,最初に持ってる金額,手数料,closeの値でトレード)
                bt = Backtest(df_, AROONt, cash=100000, commission=spread*0.0001, trade_on_close=True)
                n=list(range(8, 20, 2))
                r=list(range(6, 24, 3))
                a=list(range(1, 13, 2))
                #最適化
                stats = bt.optimize(n=n,r=r,a=a,maximize=opt_factor)
                print(stats)
                #そのままの形では最適な時のパラメータを読み取れないので，一度csvに保存してデータフレームとして取得
                stats.to_csv(path_opt, index=True, header=True)
                #bt.plot()
                df = pd.read_csv(path_opt, index_col=0)
                #最終的な所持金を表示
                result = df.at['Equity Final [$]','0']
                AROONresult = float(result)
                print('Equity Final [$] =',AROONresult)
                
                #パラメータを抽出
                saiteki = df.at['_strategy','0']
                num = re.findall('\d+',saiteki)
                AROONvalue = int(num[0])
                ATRvalue = int(num[1])
                ATRweight = int(num[2])
                print('AROON =',AROONvalue)
                print('ATR =',ATRvalue)
                print('ATRweight =',ATRweight)

                #パラメータをcsvに保存
                cols = ['AROON','ATR','ATRweight']
                aroon_frame = pd.DataFrame(index=[], columns=cols)
                aroon_data = pd.Series( [AROONvalue,ATRvalue,ATRweight], index=aroon_frame.columns )
                aroon_frame = aroon_frame.append(aroon_data, ignore_index=True)
                aroon_frame.to_csv(path_para, index=True, header=True)

    except pd.errors.EmptyDataError:
        print('csvファイルが読み取れませんでした．スキップします．')
        continue

    except ValueError:
        print('ValueError')
        continue

    except AssertionError:
        print('AssertionError')
        continue

    except TypeError:
        print('TypeError')
        continue

    except AttributeError:
        print('AttributeError')
        continue

    except OverflowError:
        print('OverflowError')
        continue
    
    except OSError:
        print('OSError')
        continue



    #ほかのインジケーターも全部同じことしてます(コメント面倒だったからこれしか書いてません)
    