Overall Statistics |
Total Trades 0 Average Win 0% Average Loss 0% Compounding Annual Return 0% Drawdown 0% Expectancy 0 Net Profit 0% Sharpe Ratio 0 Loss Rate 0% Win Rate 0% Profit-Loss Ratio 0 Alpha 0 Beta 0 Annual Standard Deviation 0 Annual Variance 0 Information Ratio 0 Tracking Error 0 Treynor Ratio 0 Total Fees $0.00 |
from clr import AddReference AddReference("System") AddReference("QuantConnect.Algorithm") AddReference("QuantConnect.Common") from System import * from QuantConnect import * from QuantConnect.Algorithm import * from QuantConnect.Data import * import tensorflow as tf import numpy as np import pandas as pd from Model import Model from datetime import datetime, timedelta from sklearn.preprocessing import normalize from collections import deque from decimal import Decimal from clr import AddReference AddReference("System") AddReference("QuantConnect.Algorithm") AddReference("QuantConnect.Common") ### <summary> ### Basic template algorithm simply initializes the date range and cash. This is a skeleton ### framework you can use for designing an algorithm. ### </summary> class BasicTemplateAlgorithm(QCAlgorithm): '''Basic template algorithm simply initializes the date range and cash''' def Initialize(self): '''Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.''' self.TimeSpan = 15 # Este es el periodo de las barras que vamos a crear self.BarPeriod = TimeSpan.FromMinutes(self.TimeSpan) self.RollingWindowSize = 50 # Mantiene los datos identificados por simbolos self.Data = {} # Lista de activos self.assets = ["AAPL", "IBM", "MSFT"] self.equities = [] self.tickets = [] for asset in self.assets: equity = self.AddEquity(asset, Resolution.Hour) self.equities.append(equity) self.tickets.append(None) #self.Data[asset] = SymbolData(equity.Symbol, self.BarPerimid, self.RollingWindowSize) # Definir carácteristicas self.features = ["close", "high", "low"] self.f = len(self.features) self.m = len(self.assets) self.n = self.RollingWindowSize self.initial_value = 10000 # Fecha de incio self.SetStartDate(2016, 1, 1) # Fecha final self.SetEndDate(2016, 1, 2) # self.SetEndDate(datetime.now() - timedelta(1)) # Fondo inicial self.SetCash(self.initial_value) # Portafolio inicial self.portfolio_memory = [] self.initial_portfolio = np.full( [self.m], 1/self.m) self.portfolio_memory.append(self.initial_portfolio) self.portfolio_memory.append(self.initial_portfolio) self.array_portfolio_array = np.array(self.portfolio_memory) self.con_mat = np.cov(self.array_portfolio_array.T) # Número de entrenamientos self.epoch = 1 self.initializer = tf.contrib.layers.variance_scaling_initializer() self.learning_rate = 0.00028 self.discount_rate = 0.95 self.t_episodes = 20 self.amplification_learning_factor = 1 self.t_batch = 100 self.t_mini_batch = 1 self.t_steps = 100 self.model = Model(batch_num = self.t_mini_batch, num_features= self.f, num_assets=self.m, num_periods=self.n, initial_value=self.initial_value, learning_rate=self.learning_rate, discount_rate=self.discount_rate, training_episodes = self.t_episodes) # Bucle por todos los simbolos para requerir la suscripcion de datos for symbol, symbolData in self.Data.items(): # definir el consolidador para consolidar los datos de este simbolo en el periodo requerido consolidator = TradeBarConsolidator(self.BarPeriod) if symbolData.Symbol.SecurityType == SecurityType.Equity else QuoteBarConsolidator(self.BarPeriod) # Agragar funcion a evento para poner al dia los datos consolidator.DataConsolidated += self.OnDataConsolidated # suscribrir el consolidador para que se actualice automaticamente cuanto ocurra el evento self.SubscriptionManager.AddConsolidator(symbolData.Symbol, consolidator) # Evento porgramado cada 15 minutos self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.Every(timedelta(minutes=self.TimeSpan)), self.OnDataPeriod) self.Debug("Primero entrenemos el modelo") self.train_model() self.model.trained = True self.Debug("OK. Modelo entrenedado") def OnDataConsolidated(self, sender, bar): self.Data[bar.Symbol.Value].BarsData.append(np.array([bar.Close, bar.High, bar.Low])) def OnDataPeriod(self): self.norm_prices, self.current_prices, self.previous_prices = self.obtain_prices() if not isinstance(self.norm_prices, np.ndarray): return self.model.set_prices(self.norm_prices, self.current_prices, self.previous_prices) next_w = self.model.predict() if (self.epoch % self.t_episodes == 0): self.episode_count, self.steps_count, self.current_rewards, self.all_rewards, self.loss = self.model.train() self.Debug(" ") self.Debug("==========================================") self.Debug("Episodio: " + str(self.episode_count)) self.Debug("Paso: " + str(self.episode_count * self.steps_count)) self.Debug("-----------") self.Debug("Media de la ganancia: " + str(np.mean(self.current_rewards))) self.Debug("Promedio de ganancias en todos los entrenamientos: " + str(np.mean(self.all_rewards))) self.Debug("Perdida del episodio: " + str(self.loss)) if self.epoch > self.t_steps: if self.epoch % 48 == 0: for asset in range(len(self.assets)): """ quantity = Decimal(float(self.Portfolio.TotalPortfolioValue) * next_w[asset] / self.current_prices[asset]) if self.tickets[asset] == None: self.tickets[asset] = self.MarketOrder(self.assets[asset], quantity) if self.tickets[asset] != None: self.Debug("Orden enviada") else: updateOrderFields = UpdateOrderFields() updateOrderFields.Quantity = quantity self.tickets[asset].Update(updateOrderFields) """ self.SetHoldings(self.assets[asset], next_w[asset], False) self.last_portfolio_value = self.Portfolio.TotalPortfolioValue #self.Portfolio.TotalAbsoluteHoldingsCost + self.Portfolio.TotalUnrealisedProfit + self.Portfolio.Cash self.Debug("Step: " + str(self.epoch) + " Portafolio Value: " + str(self.last_portfolio_value)) #+ " - Omega: " + str(new_w[0]) + " - Reward: " + str(reward_val)) self.epoch = self.epoch + 1 else: # self.Debug("Step: " + str(self.model.steps_count)+ " Status: Training") self.epoch = self.epoch + 1 # GANANCIAS NORMALIZADAS def discount_rewards(self, rewards, discount_rate): discounted_rewards = np.empty(len(rewards)) cumulative_rewards = 0 for step in reversed(range(len(rewards))): cumulative_rewards = rewards[step] + cumulative_rewards * discount_rate discounted_rewards[step] = cumulative_rewards return discounted_rewards def discount_and_normalize_rewards(self, rewards, discount_rate): discounted_rewards = self.discount_rewards(rewards, discount_rate) reward_mean = discounted_rewards.mean() reward_std = discounted_rewards.std() normalized_rewards = (discounted_rewards - reward_mean)/reward_std return normalized_rewards def get_training_prices(self): # Crear ventana de datos. back_bars = self.TimeSpan * self.t_batch h1 = self.History(self.Securities.Keys, back_bars, Resolution.Minute) # Filtrar las características deseadas h1 = h1.loc[self.assets][self.features].fillna(method='ffill').fillna(method='bfill') raw_prices = np.zeros(shape=(self.m,self.t_batch,self.f), dtype=np.float64) for asset in range(len(self.assets)): period = 0 for i in range(self.t_batch * self.TimeSpan): if i % self.TimeSpan == 0 and i > 0: ran = h1.loc[self.assets[asset]][:][i:i+self.TimeSpan].values self.Debug(str(ran.shape)) close = ran[-1][0] high = np.max(ran[:][1]) low = np.min(ran[:][2]) raw_prices[asset][period][0] = close raw_prices[asset][period][1] = high raw_prices[asset][period][2] = low period += 1 # Normalizar los valores para entrar en red neuronal """ for asset in range(self.m): norm_prices[asset] = normalize(norm_prices[asset]) """ return raw_prices def obtain_prices(self): # Crear ventana de datos. h1 = self.History(self.Securities.Keys, 50, Resolution.Minute).fillna(method='ffill').fillna(method='bfill') # Definir formato de precios (assets=3, periods=50, features=3) norm_prices = np.zeros(shape=(self.m,self.n,self.f), dtype=np.float64) a = 0 for k, v in self.Data.items(): if self.Data[k].IsReady(): if np.array(v.BarsData).shape == norm_prices[a].shape: norm_prices[a] = np.array(self.Data[k].BarsData) a += 1 else: self.Debug("Sin datos suficientes") self.Debug(str(np.array(v.BarsData).shape)) self.Debug(str(norm_prices[a].shape)) return None, None, None # Normalizar los valores para entrar en red neuronal for asset in range(self.m): norm_prices[asset] = normalize(norm_prices[asset]) current_prices = [] previous_prices = [] for asset in self.assets: current_prices.append(h1.loc[asset]["close"][-1]) for asset in self.assets: previous_prices.append(h1.loc[asset]["close"][-2]) return norm_prices, current_prices, previous_prices def train_model(self): # Crear ventana de datos. back_bars = self.TimeSpan * self.t_batch self.Debug("Obtengamos los datos") data = self.get_training_prices() self.Debug("Datos obtenidos: " + str(data.shape)) for i in range(self.t_steps): # Get Data Slice self.norm_prices = np.empty((0,self.m, self.n, self.f)) prices_shape = np.zeros(shape=(self.m,self.n,self.f), dtype=np.float64).shape data_slice = data[:, i:i + 50, :] if data_slice.shape == prices_shape: norm_prices = data_slice # Normalizar los valores para entrar en red neuronal for asset in range(self.m): norm_prices[asset] = normalize(norm_prices[asset]) else: self.Debug("Formas no consistentes en slice: " + str(data_slice.shape) + " " + str(prices_shape)) return self.norm_prices = np.append(self.norm_prices, [norm_prices], axis=0) self.current_prices = [] self.previous_prices = [] for batch in range(self.t_mini_batch): current_prices = [] previous_prices = [] for asset in range(self.m): current_prices.append(data_slice[asset,-1,0]) previous_prices.append(data_slice[asset,-2,0]) self.current_prices.append(current_prices) self.previous_prices.append(previous_prices) if not isinstance(self.norm_prices, np.ndarray): return self.model.set_prices(self.norm_prices, self.current_prices, self.previous_prices) next_w = self.model.predict_batch() if (self.epoch % self.t_episodes == 0 and self.epoch > 0): self.episode_count, self.steps_count, self.current_rewards, self.all_rewards, self.loss = self.model.train_batch() self.Debug(" ") self.Debug("==========================================") self.Debug("Episodio: " + str(self.episode_count)) self.Debug("Paso: " + str(self.episode_count * self.steps_count)) self.Debug("-----------") self.Debug("Media de la ganancia: " + str(np.mean(self.current_rewards))) self.Debug("Promedio de ganancias en todos los entrenamientos: " + str(np.mean(self.all_rewards))) self.Debug("Perdida del episodio: " + str(self.loss)) self.epoch = self.epoch + 1 def OnData(self, data): return class SymbolData(object): def __init__(self, symbol, barPeriod, windowSize): self.Symbol = symbol self.BarPeriod = barPeriod self.WindowSize = windowSize self.BarsData = deque(maxlen=self.WindowSize) def IsReady(self): if len(self.BarsData) == self.WindowSize: return True else: return False
from clr import AddReference AddReference("System") AddReference("QuantConnect.Algorithm") AddReference("QuantConnect.Common") from System import * from QuantConnect import * from QuantConnect.Algorithm import * from QuantConnect.Data import * import tensorflow as tf import numpy as np import pandas as pd from datetime import datetime, timedelta from sklearn.preprocessing import normalize class Model: def __init__(self, batch_num, num_features, num_assets, num_periods, initial_value, learning_rate, discount_rate, training_episodes): self.t_episodes = training_episodes self.batch_num = batch_num self.f = num_features self.m = num_assets self.n = num_periods self.initial_value = initial_value self.learning_rate = learning_rate self.discount_rate = discount_rate self.commission_rate = 0.01 self.there_is_model = False self.all_rewards = [] self.current_rewards = [] self.portfolio_memory = [] self.initial_portfolio = np.full( [self.m], 1/self.m) self.portfolio_memory.append(self.initial_portfolio) self.portfolio_memory.append(self.initial_portfolio) self.array_portfolio_array = np.array(self.portfolio_memory) self.cov_mat = np.cov(self.array_portfolio_array.T) self.policy = np.random.multivariate_normal(self.initial_portfolio, self.cov_mat) self.previous_prices = np.zeros(shape=(self.m,self.n,self.f), dtype=np.float64) self.norm_prices = np.zeros(shape=(self.m,self.n,self.f), dtype=np.float64) self.current_prices = np.zeros(shape=(self.m,self.n,self.f), dtype=np.float64) self.episode_count = 1 self.steps_count = 0 self.trained = False self.setup_network() def discount_rewards(self, rewards, discount_rate): discounted_rewards = np.empty(len(rewards)) cumulative_rewards = 0 for step in reversed(range(len(rewards))): cumulative_rewards = rewards[step] + cumulative_rewards * discount_rate discounted_rewards[step] = cumulative_rewards return discounted_rewards def discount_and_normalize_rewards(self, rewards, discount_rate): discounted_rewards = self.discount_rewards(rewards, discount_rate) reward_mean = discounted_rewards.mean() reward_std = discounted_rewards.std() normalized_rewards = (discounted_rewards - reward_mean)/reward_std return normalized_rewards def set_prices(self, norm_prices, current_prices, previous_prices): self.current_prices = current_prices self.norm_prices = norm_prices self.previous_prices = previous_prices def next_step(self): self.steps_count = self.setps_count + 1 def train_batch(self): previous_w_val = self.portfolio_memory[-1] self.previous_w_val = np.empty((0,self.m)) for i in range(self.batch_num): self.previous_w_val = np.append(self.previous_w_val, [previous_w_val], axis=0) discounted_rewards = np.empty((0,self.t_episodes)) for i in range(self.batch_num): discounted_rewards = np.append(discounted_rewards, [self.discount_and_normalize_rewards(self.current_rewards, self.discount_rate)], axis=0) policy = np.empty((0,self.m)) for i in range(self.batch_num): policy = np.append(policy, [self.policy], axis=0) loss_, _ = self.sess.run([self.loss, self.training_op], feed_dict={self.prices: self.current_prices, self.x: self.norm_prices, self.previous_w: self.previous_w_val, self.actions: policy, self.discounted_episode_rewards: discounted_rewards }) episode_count = self.episode_count steps_count = self.steps_count current_rewards = self.current_rewards self.steps_count = 0 self.episode_count = self.episode_count + 1 self.all_rewards.append(self.current_rewards) self.current_rewards = [] return episode_count, steps_count, current_rewards, self.all_rewards, loss_ def train(self): self.previous_w_val = self.portfolio_memory[-1] discounted_rewards = self.discount_and_normalize_rewards(self.current_rewards, self.discount_rate) loss_, _ = self.sess.run([self.loss, self.training_op], feed_dict={self.prices: [self.current_prices], self.x: [self.norm_prices], self.previous_w:[self.previous_w_val], self.actions:[self.policy], self.discounted_episode_rewards: [discounted_rewards] }) episode_count = self.episode_count steps_count = self.steps_count current_rewards = self.current_rewards self.steps_count = 0 self.episode_count = self.episode_count + 1 self.all_rewards.append(self.current_rewards) self.current_rewards = [] return episode_count, steps_count, current_rewards, self.all_rewards, loss_ def predict_batch(self): previous_w_val = self.portfolio_memory[-1] self.previous_w_val = np.empty((0,self.m)) for i in range(self.batch_num): self.previous_w_val = np.append(self.previous_w_val, [previous_w_val], axis=0) new_w = self.soft_max.eval(session=self.sess, feed_dict={self.x: self.norm_prices, self.previous_w:self.previous_w_val }) reward = np.sum(self.current_prices * new_w[0] - self.previous_prices * self.previous_w_val) - np.sum(self.current_prices * new_w[0]) * self.commission_rate self.current_rewards.append(reward) self.portfolio_memory.append(new_w[0]) self.cov_mat = np.cov(self.array_portfolio_array.T) self.policy = np.random.multivariate_normal(new_w[0], self.cov_mat) self.steps_count = self.steps_count + 1 return self.policy def predict(self): self.previous_w_val = self.portfolio_memory[-1] new_w = self.soft_max.eval(session=self.sess, feed_dict={self.x: [self.norm_prices], self.previous_w:[self.previous_w_val] }) reward = np.sum(self.current_prices * new_w[0] - self.previous_prices * self.previous_w_val) - np.sum(self.current_prices * new_w[0]) * self.commission_rate self.current_rewards.append(reward) self.portfolio_memory.append(new_w[0]) self.cov_mat = np.cov(self.array_portfolio_array.T) self.policy = np.random.multivariate_normal(new_w[0], self.cov_mat) self.steps_count = self.steps_count + 1 return self.policy def setup_network(self): self.sess = tf.InteractiveSession() self.x = tf.placeholder(tf.float32, [None, self.m, self.n, self.f]) self.previous_w = tf.placeholder(tf.float32, [None, self.m]) self.prices = tf.placeholder(tf.float32, [None, self.m]) self.actions = tf.placeholder(tf.float32, [None, self.m]) self.discounted_episode_rewards = tf.placeholder(tf.float32, [None, self.t_episodes]) # La forma final debe ser (features, periods, assets) self.x = tf.transpose(self.x, [0, 1, 2, 3]) # Capa Convolucional #1 self.conv1 = tf.layers.conv2d( inputs=self.x, filters=2, kernel_size=[1, 3], padding="valid", activation=tf.nn.relu, kernel_initializer=None, bias_initializer=tf.zeros_initializer()) self.width = self.conv1.get_shape()[2] # Capa Convolucional #2 self.conv2 = tf.layers.conv2d( inputs=self.conv1, filters=20, kernel_size=[1,self.width], padding="valid", activation=tf.nn.relu, kernel_initializer=None, bias_initializer=tf.zeros_initializer(), kernel_regularizer=tf.contrib.layers.l2_regularizer(scale=5e-09)) # Capa Totalmente Conectada #3 self.fc = tf.layers.flatten(self.conv2) self.fc = tf.concat([self.fc, self.previous_w], axis=1) self.fc = tf.contrib.layers.fully_connected(inputs=self.fc, num_outputs=self.m, activation_fn=tf.nn.softmax, weights_regularizer=tf.contrib.layers.l2_regularizer(scale=5e-09) ) # self.soft_max = tf.concat([self.cash, self.fc], axis=1) self.soft_max = tf.nn.softmax(self.fc) self.neg_log_prob = tf.nn.softmax_cross_entropy_with_logits_v2(logits = self.soft_max, labels = self.actions) self.loss = tf.reduce_mean(self.neg_log_prob * self.discounted_episode_rewards) """ self.loss = ( -tf.reduce_mean(tf.log(tf.reduce_sum(self.prices * self.fc) / self.initial_value)) ) + \ self.discount_rate * ( tf.reduce_mean(tf.reduce_sum(-tf.log(1 + 1e-6 - self.fc) / self.initial_value)) ) """ self.optimizer = tf.train.AdamOptimizer(learning_rate=self.learning_rate) self.training_op = self.optimizer.minimize(self.loss) self.sess.run(tf.global_variables_initializer())