Example #1
0
    print 'Bin Location is: ', location
"""
if __name__ == '__main__':
    #location to store files
    relativePath = "/home/pi/BinFunGame/src/TempFiles/"
    
    mainDeque = deque()
    
    #Init buffer
    location = raw_input('Please enter currect location of bin:')
    #location = str(main(sys.argv[1:]))
    binBuffer = Buffer(location, "black", "green", "blue", "grey")
    time.sleep(10)
    
    #Clean buffer
    binBuffer.clear()
    
    binEmptyFlag = True
    
    #Init sdFile
    #headers = "ID,Location,Date,Time"
    sdFile = SDfile(relativePath, location)
    #sdFile.quickInit(headers)

    #Init database
    db = Database("54.218.32.132", "bfguser", "bfg123", "bfg")
    
    #Init global variables
    globalVars.init()

    #Start display thread
Example #2
0
class Portfolio_managment:
    """
        Objet portefeuille.
        Base de tout le projet, il permet à l'aide de la méthode simulate d'entrainer notre modèle (DEEP RL)
        Pour créer un portefeuille, il faut renseigner les inputs suivants :
        Input :
            symbols : Liste de currencies extractables via l'API bitfinex
                type : liste
            period_start : Date de début à laquelle on doit télécharger les données, on choisit une date où toutes les cryptos sont déjà existantes (ne prends pas en compte les NA)
                type : datetime
            period_end : Date de fin de la période où la requete va télécharger les données.
                type : datetime
        /!\ Attention : Penser à supprimer les données du répertoire DATA si vous souhaitez rechargez à une autre date /!\
            Choix de ce pour des raisons de gains de temps, les données peuvent mettre du temps à se télécharger.
            mode : train ou test
                type : string
        Les inputs qui suivent sont optionnelles et permettent une optimisation des résultats via une GridSearchCV. 
        A noter que d'autres paramètres choisit comme constant par nous même peuvent être aussi optimiser (EX : la taille des batch, du buffer, le nombre de features etc etc)
            CASH_BIAIS : Incitation ou non à garder du cash
                type : integer
            WINDOW_SIZE : Nombre de periode à prendre en compte par le modèle à chaque step
                type : integer
            LR : Learning Rate
                type : float
            MODEL_NAME : Nom du résaux de neurones à utiliser (deux disponibles ici : CNN et CNN_LSTM (+ long à compute))
                type : string
    """
    def __init__(self, symbols,period_start,period_end,mode,CASH_BIAS = 0,WINDOW_SIZE = 48,LR = 2e-5,MODEL_NAME = 'CNN',reward = 'avg_log_cum_return'):
        tf.compat.v1.disable_eager_execution() # permet l'utilisation complète de Tensorflow 1
        self.symbols = symbols
        self.period_start = period_start
        self.period_end = period_end
        self.symbols_num = len(symbols)
        self.mode = mode
        self.nb_ep = 0
        self.MODEL_NAME = MODEL_NAME
        #HYPER PARAMETERS
        self.BUFFER_SIZE = 200
        self.BATCH_SIZE = 10
        self.SHOW_EVERY = WINDOW_SIZE*7*4 #Affichage des résultats tous les MOIS (30jours)
        self.WINDOW_SIZE = WINDOW_SIZE # Une journée
        self.CASH_BIAS = CASH_BIAS 
        self.NB_FEATURES = 9 
        self.SAMPLE_BIAS = 1.05 
        self.state_dim = (self.symbols_num,self.WINDOW_SIZE,self.NB_FEATURES)
        self.action_size = self.symbols_num +1
        self.LR_list = {'train':2e-5,'test':9e-5,'valid':9e-5}
        self.ROLLING_STEPS_dic = {'train':1,'test':0,'valid':0}
        self.ROLLING_STEPS = self.ROLLING_STEPS_dic[mode]
        if LR in [2e-5,9e-5]:
            self.LR = self.LR_list[mode]
        else:
            self.LR = LR
        #Initialisation 
        self.episode_reward = []
        self.total_step = 0
        self.session = self.tf_session()
        np.random.seed(4)
        self.agent = Agent(self.session,self.state_dim,self.action_size,self.BATCH_SIZE,self.LR,reward,MODEL_NAME)
        self.buffer = Buffer(self.BUFFER_SIZE, self.SAMPLE_BIAS)
    def tf_session(self):
        """
            Initialisation de la session tensorflow + keras.
            Ici, on va utiliser uniquement le GPU et nous lui allouons le plus de capacité possible. 
            Possibilité certaine d'optimiser le temps de traitement via une distribution sur plusieurs GPU mais nous n'avons pas encore trouvé comment le faire.
        """
        config = tf.compat.v1.ConfigProto()
        config.gpu_options.allow_growth = True
        config.gpu_options.per_process_gpu_memory_fraction = 1
        sess = tf.compat.v1.Session(config=config)
        tf.compat.v1.keras.backend.set_session(sess)
        tf.compat.v1.keras.backend.set_learning_phase(1)
        return sess
    def simulate(self,episode_depart,episode_fin,poids=None):
        """
            Méthode COEUR pour générer nos résultats.
            Input :
                episode_depart : Episode pour lequel notre modèle va démarrer. Peut être un épisode autre que 0 et va donc puiser dans les anciens poids pour continuer 
                    type : int
                episode_fin : Episode de fin du traitement
                    type : int
            Output :
                Les différents rendements cumulés en fonction des épisodes
        """
        all_ = []
        self.nb_ep = episode_fin - episode_depart
        root_path = f'Model/Model_{self.MODEL_NAME}_{str(self.period_start)[:10]}_{str(self.period_end)[:10]}_nbep_{self.nb_ep}'
        #Premiere boucle sur les épisodes (episode 1 à episode depoart + episode fin)
        for episode in tqdm(range(episode_depart+1,episode_depart+episode_fin+1)):
            #Chargement des poids existants si c'est possible
            if poids != None and episode == episode_depart+1:
                print('loading train weight')
                self.agent.model.load_weights(poids)
            else:
                if not (self.mode == 'train' and episode ==episode_depart+1):
                    self.charger_poids(episode)
            #On instancie à chaque nouvel épisode notre objet portefeuille
            Port = Portfeuille(self.symbols,self.period_start,self.period_end,'BTCUSD')
            #Préparation des états
            state = self.states(Port,self.WINDOW_SIZE)
            cum_return = 1
            lst_returns = []
            #Deuxieme boucle sur toute la période
            for step in range(len(state)-2):
                if step == 0:
                    last_action = np.ones(self.state_dim[0])
                else:
                    last_action = np.array(Port.weights[-1][:self.state_dim[0]])
                #les différents inputs de notre model suivant un format très précis
                reshape1 = state[step].reshape([1,self.state_dim[2],self.state_dim[1],self.state_dim[0]])
                reshape2 = last_action.reshape([1,self.state_dim[0]])
                reshape3 =np.array([[self.CASH_BIAS]])
                #Notre réallocation des poids action[0]
                action = self.agent.model.predict([reshape1,reshape2,reshape3])
                #calcul des rendements
                rendement_jour, futur_price = Port.get_return(action[0],last_action,step)
                self.replay(state,step,futur_price,last_action)
                cum_return *= rendement_jour
                self.total_step +=1
                #Affichage des résultats tous les x pas
                if not step % self.SHOW_EVERY:
                    print(f"Episode {episode}, pas {step}\nCumReturn {cum_return} à la date : {Port.df_close.iloc[Port.idx_depart + step+1].name}")
                    print(action[0])
                lst_returns.append(rendement_jour)
            #Calcul de différents indicateurs de performances
            SR = self.sharpe_ratio(lst_returns)
            #SR_BTC = self.sharpe_ratioBTC(lst_returns,Port.cash)
            MD = self.maximum_drawdown(lst_returns)
            VOL = self.volatitile(lst_returns)
            #Nettoyage de notre buffer
            self.buffer.clear()
            self.episode_reward.append(cum_return)
            #Enregistrement des poids pour récupérations plus tard 
            self.enregistrer_poids(episode,Port,cum_return)
            all_ += [(cum_return,SR,'SR_BTC',MD,VOL)]
        #on enregistre les performances dans un petit csv
        pd.DataFrame(all_,columns=['cum_return','SR','SR_BTC','MD','Vol']).to_csv(f'{root_path}/Resultats/perf.csv')
        return self.episode_reward,all_
    def replay(self,state,step,futur_price,last_action):
        """
            Permet d'accélérer la phase d'apprentissage du réseau de neurones.
            On réutilise les précédents inputs, le model est alors nourri et updaté par mini batch.
            Mix de data mélangés récentes,anciennes ou rares et fréquentes.
            Input : 
                state : ensemble des états obtenus
                    type : liste
                step : pas
                    type : int
                futur_price : prochain prix
                    type : array 
                last_action : dernier vecteur de poids calculés
                    type : liste
        """
        self.buffer.add(state[step],futur_price,last_action)
        for _ in range(self.ROLLING_STEPS):
            batch,current_batch_size = self.buffer.getBatch(self.BATCH_SIZE)
            states = np.asarray([i[0] for i in batch])
            futur_prices = np.asarray([i[1] for i in batch])
            last_actions = np.asarray([i[2] for i in batch])
            cash_biass = np.array([[self.CASH_BIAS] for _ in range(current_batch_size)])
            if step > 10:
                self.agent.train(states,last_actions,futur_prices,cash_biass)
    def states(self,portefeuille,window_size):
        """
            Permet d'obtenir les différents états du portefeuille sur une plage de temps (window_size) donnée
        """
        state = []
        df = np.array([portefeuille.df_close.values,portefeuille.df_high.values,
                        portefeuille.df_low.values,portefeuille.df_volume.values,
                        portefeuille.df_roc.values,portefeuille.df_macd.values,
                        portefeuille.df_ma3j.values,portefeuille.df_ma7j.values,
                        portefeuille.df_ema14j.values], dtype='float')
        for j in range(portefeuille.idx_depart -1, len(df[0])):
            temp = np.copy(df[:, j-window_size+1:j+1 , :])
            for feature in [0,1,2,3]:
                for k in range(portefeuille.num_symbols):
                    if temp[feature,-1,k] == 0:
                        temp[feature,:,k] /= temp[feature,-2,k]
                    else:
                        temp[feature,:,k] /= temp[feature,-1,k]
            state.append(temp)
        return state
    def charger_poids(self,ep):
        """
            Charge les poids sauvegardés à l'épisode précédent pour améliorer les résultats
        """
        root_path = f'Model/Model_{self.MODEL_NAME}_{str(self.period_start)[:10]}_{str(self.period_end)[:10]}_nbep_{self.nb_ep}'
        if self.mode == 'train' or self.mode =="valid":
            self.agent.model.load_weights(f"{root_path}/Poids/Agent_poids_{self.mode}_ep_{ep-1}.h5")
        else:
            self.agent.model.load_weights(f"{root_path}/Poids/Agent_poids_test_ep_{ep-1}.h5")
    def enregistrer_poids(self,ep,Port,cum_return):
        """
            Sauvegarde les poids du model
        """
        root_path = f'Model/Model_{self.MODEL_NAME}_{str(self.period_start)[:10]}_{str(self.period_end)[:10]}_nbep_{self.nb_ep}'
        if not os.path.exists(root_path):
            os.mkdir(root_path)
            os.mkdir(f'{root_path}/Poids')
            os.mkdir(f'{root_path}/Resultats')
        if self.mode == "train":
            self.agent.model.save_weights(f"{root_path}/Poids/Agent_poids_{self.mode}_ep_{ep}.h5", overwrite=True)
        elif self.mode =="valid" or self.mode =="test":
            self.agent.model.save_weights(f"{root_path}/Poids/Agent_poids_{self.mode}_ep_{ep}.h5", overwrite=True)
        filename = 'Portfolio_{}_{}_{}_{}_{}.pickle'.format(self.mode,str(Port.start)[:10],str(Port.end)[:10],'-'.join(Port.symbols), cum_return)
        with open("{}/Resultats/{}".format(root_path,filename),"wb") as outfile:
            pickle.dump(Port, outfile)
            print("Sauvegardé sous {}/Resultats/{}".format(root_path,filename) )
    #Mesure des performances
    def rendements_cumules(self,lst_rendements_jours):
        """
            Obtention des rendements cumulées
            Input:
                liste des rendements 
            Output:
                rendement cumulés
        """
        return np.cumprod(np.array(lst_rendements_jours))
    def sharpe_ratio(self,lst_rendements_jours):
        """
            Input :
                liste des rendements
            Output :
                Sharpe Ratio
            Formule : Sharpe Ratio = (PR)/SD 
                PR <- Portfolio return
                RFR <- Taux de l'actif sans risque
        """
        pr = np.log(np.array(lst_rendements_jours))
        return (np.sqrt(len(pr))*np.mean(pr))/np.std(pr)
    def sharpe_ratioBTC(self,lst_rendements_jours,cash):
        """
            Input :
                liste des rendements 
            Output :
                Sharpe Ratio
            Formule : Sharpe Ratio = (PR - RFR)/SD 
                PR <- Portfolio return
                RFR <- Taux de l'actif sans risque
        """
        pr = np.log(np.array(lst_rendements_jours))
        rcash = np.log(np.array(cash))
        return (np.sqrt(len(pr))*np.mean(pr - rcash))/np.std(pr - rcash)
    def maximum_drawdown(self,lst_rendements):
        """
        Calcul du drowdown maximal
        """
        val_pf = []
        lst_drawdown = []
        benef_max = 0
        lst_rendements = np.array(lst_rendements)
        for i in range(lst_rendements.shape[0]):
            if i > 0:
                val_pf.append(val_pf[i - 1] * lst_rendements[i])
            else:
                val_pf.append(lst_rendements[i])
            if val_pf[i] > benef_max:
                benef_max = val_pf[i]
                lst_drawdown.append(0)
            else:
                lst_drawdown.append(1 - val_pf[i] / benef_max)
        return max(lst_drawdown)
    def volatitile(self,lst_rendements):
        """
            Renvoi la volatilité de la série
        """
        return np.std(np.log(np.array(lst_rendements)))
Example #3
0
                                        episode_length=timestep)

                # Initialize env after end of episode
                obs = env.reset()
                episode_rewards.clear()
                episode += 1

                if timestep >= TIMESTEPS_PER_EPOCH or timestep > 10000:
                    break

        # Save model
        if epoch % 100 == 0:
            try:
                model.save(epoch=epoch, run_name=RUN_NAME)
            except:
                print('ERROR calling model.save()')

        # Train model on epoch data
        epoch_info = model.learn_from_experience(
            data=buf.get(),
            normalize_returns=NORMALIZE_REWARDS,
            entropy_coeff=ENTROPY_COEFF,
            clip_grad=CLIP_GRAD)

        # Log epoch statistics and clear buffer
        log.log_epoch(epoch, epoch_info)
        buf.clear()

    # After Training
    model.save(epoch=epoch, run_name=RUN_NAME)
    env.close()