Overall Statistics |
Total Trades 9193 Average Win 0.00% Average Loss 0.00% Compounding Annual Return 2.962% Drawdown 4.200% Expectancy -0.356 Net Profit 0.463% Sharpe Ratio 0.306 Loss Rate 70% Win Rate 30% Profit-Loss Ratio 1.11 Alpha -0.091 Beta 7.528 Annual Standard Deviation 0.089 Annual Variance 0.008 Information Ratio 0.129 Tracking Error 0.088 Treynor Ratio 0.004 Total Fees $0.00 |
from clr import AddReference AddReference("System") AddReference("QuantConnect.Algorithm") AddReference("QuantConnect.Algorithm.Framework") AddReference("QuantConnect.Common") from System import * from QuantConnect import * from QuantConnect.Orders import * from QuantConnect.Algorithm import * from QuantConnect.Brokerages import * from QuantConnect.Algorithm.Framework import * from QuantConnect.Algorithm.Framework.Alphas import * from QuantConnect.Algorithm.Framework.Execution import * from QuantConnect.Algorithm.Framework.Portfolio import * from QuantConnect.Algorithm.Framework.Risk import * from QuantConnect.Algorithm.Framework.Selection import * from QuantConnect import Resolution, Extensions from itertools import groupby from datetime import datetime, timedelta from pytz import utc UTCMIN = datetime.min.replace(tzinfo=utc) import io, requests import numpy as np import pandas as pd class BasicTemplateFrameworkAlgorithm(QCAlgorithmFramework): def Initialize(self): self.SetStartDate(2019,1,3) #Set Start Date self.SetEndDate(2019,3,1) #Set End Date self.SetCash(100000) #Set Strategy Cash self.SetBrokerageModel(BrokerageName.OandaBrokerage) self.weights = {} assets = ['AUDUSD', 'EURUSD', 'GBPUSD', 'NZDUSD', 'USDCAD', 'USDCHF', 'USDJPY', 'USDNOK', 'USDSEK', 'USDSGD'] self.UniverseSettings.Resolution = Resolution.Hour symbols = [ Symbol.Create(asset, SecurityType.Forex, Market.Oanda) for asset in assets ] self.SetUniverseSelection( ManualUniverseSelectionModel(symbols) ) self.SetAlpha(CustomAlphaModel(assets=assets, No_Channels = 10, Input_Size = 256, func = self.CalculateWeights)) self.SetPortfolioConstruction(CustomWeightingPortfolioConstructionModel(resolution = Resolution.Daily, func = self.CalculateWeights, Input_Size = 256)) self.SetExecution(ImmediateExecutionModel()) self.SetRiskManagement(NullRiskManagementModel()) def CalculateWeights(self, assets, securities, Input_Size): history_df = self.History(assets, timedelta(14), Resolution.Hour) return_weights = {} for security in securities: symbol = security.Value.Symbol.Value cc = None if str(symbol) not in history_df.index.get_level_values(0): continue history = history_df.loc[str(symbol)] df = history['close'].resample('1H').interpolate(method='cubic') if symbol[-3:] != 'USD': df = 1.0 / df df = np.log((df/df.shift(1)).tail(Input_Size)) if cc is None: cc = df else: cc = pd.concat([cc, df], axis=1) data = cc.values.tolist() #response = requests.post('https://api.server/model', json=data) #weights = np.array(response.json()['arr']) ## Right now this sets it as an arbitray weighting scheme -- I was having trouble fulling implementing the response/weights part ## of your code. However, if you can create the proper weights then this is dynamic and will place orders accordingly weights = [0.1, 0.1, 0.3, 0.1, 0.2, 0.25, 0.25, 0.5, 0.1, 0.1] self.Debug(str(weights)) for i, asset in enumerate(assets): howmuch = weights[i] if asset[-3:] == 'USD' else (-1.0*weights[i]) return_weights[asset] = howmuch return return_weights class CustomAlphaModel: def __init__(self, assets, No_Channels, Input_Size, func): self.assets = assets self.No_Channels = No_Channels self.Input_Size = Input_Size self.weights = {} self.CalculateWeights = func def Update(self, algorithm, data): insights = [] ## If you need to access weights, do so as below ## self.weights = self.GetWeightsFromHistoryRequest(self.assets, algorithm.ActiveSecurities) for asset in self.assets: insights.append(Insight(asset, timedelta(5), InsightType.Price, InsightDirection.Down, 0.005, None)) ## emit insights here return insights def OnSecuritiesChanged(self, algorithm, changes): pass class CustomWeightingPortfolioConstructionModel(PortfolioConstructionModel): def __init__(self, resolution, func, Input_Size): self.insightCollection = InsightCollection() self.removedSymbols = [] self.nextExpiryTime = UTCMIN self.rebalancingTime = UTCMIN self.rebalancingPeriod = Extensions.ToTimeSpan(resolution) self.CalculateWeights = func self.Input_Size = Input_Size def CreateTargets(self, algorithm, insights): targets = [] if (algorithm.UtcTime <= self.nextExpiryTime and algorithm.UtcTime <= self.rebalancingTime and len(insights) == 0 and self.removedSymbols is None): return targets self.insightCollection.AddRange(insights) # Create flatten target for each security that was removed from the universe if self.removedSymbols is not None: universeDeselectionTargets = [ PortfolioTarget(symbol, 0) for symbol in self.removedSymbols ] targets.extend(universeDeselectionTargets) self.removedSymbols = None # Get insight that haven't expired of each symbol that is still in the universe activeInsights = self.insightCollection.GetActiveInsights(algorithm.UtcTime) # Get the last generated active insight for each symbol lastActiveInsights = [] for symbol, g in groupby(activeInsights, lambda x: x.Symbol): lastActiveInsights.append(sorted(g, key = lambda x: x.GeneratedTimeUtc)[-1]) # give weighting to each security count = sum(x.Direction != InsightDirection.Flat for x in lastActiveInsights) if count == 0: percent = 0 else: insightKeys = [x.Symbol.Value for x in lastActiveInsights] percent = self.CalculateWeights(insightKeys, algorithm.ActiveSecurities, self.Input_Size) errorSymbols = {} for insight in lastActiveInsights: target = PortfolioTarget.Percent(algorithm, insight.Symbol, insight.Direction * percent[insight.Symbol.Value]) if not target is None: targets.append(target) else: errorSymbols[insight.Symbol] = insight.Symbol # Get expired insights and create flatten targets for each symbol expiredInsights = self.insightCollection.RemoveExpiredInsights(algorithm.UtcTime) expiredTargets = [] for symbol, f in groupby(expiredInsights, lambda x: x.Symbol): if not self.insightCollection.HasActiveInsights(symbol, algorithm.UtcTime) and not symbol in errorSymbols: expiredTargets.append(PortfolioTarget(symbol, 0)) continue targets.extend(expiredTargets) self.nextExpiryTime = self.insightCollection.GetNextExpiryTime() if self.nextExpiryTime is None: self.nextExpiryTime = UTCMIN self.rebalancingTime = algorithm.UtcTime + self.rebalancingPeriod return targets def OnSecuritiesChanged(self, algorithm, changes): # Get removed symbol and invalidate them in the insight collection self.removedSymbols = [x.Symbol for x in changes.RemovedSecurities] self.insightCollection.Clear(self.removedSymbols)