| 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)