| Overall Statistics |
|
Total Trades 4 Average Win 0% Average Loss -1.25% Compounding Annual Return -1.030% Drawdown 2.600% Expectancy -1 Net Profit -2.472% Sharpe Ratio -0.572 Loss Rate 100% Win Rate 0% Profit-Loss Ratio 0 Alpha -0.02 Beta 0.746 Annual Standard Deviation 0.014 Annual Variance 0 Information Ratio -1.691 Tracking Error 0.014 Treynor Ratio -0.011 Total Fees $3.60 |
from clr import AddReference
AddReference("QuantConnect.Common")
AddReference("QuantConnect.Algorithm.Framework")
AddReference("QuantConnect.Indicators")
from QuantConnect import *
from QuantConnect.Indicators import *
from QuantConnect.Algorithm.Framework.Alphas import *
class MacdMomentumAlphaModel(AlphaModel):
'''Defines a custom alpha model that uses MACD crossovers. The MACD signal line
is used to generate up/down insights if it's stronger than the bounce threshold.
If the MACD signal is within the bounce threshold then a flat price insight is returned.'''
def __init__(self,
fastPeriod = 12,
slowPeriod = 26,
signalPeriod = 9,
movingAverageType = MovingAverageType.Exponential,
resolution = Resolution.Minute):
''' Initializes a new instance of the MacdAlphaModel class
Args:
fastPeriod: The MACD fast period
slowPeriod: The MACD slow period</param>
signalPeriod: The smoothing period for the MACD signal
movingAverageType: The type of moving average to use in the MACD'''
self.fastPeriod = fastPeriod
self.slowPeriod = slowPeriod
self.signalPeriod = signalPeriod
self.movingAverageType = movingAverageType
self.resolution = resolution
self.insightPeriod = Time.Multiply(Extensions.ToTimeSpan(resolution), fastPeriod)
self.bounceThresholdPercent = 0.01
self.symbolData = {};
resolutionString = Extensions.GetEnumString(resolution, Resolution)
movingAverageTypeString = Extensions.GetEnumString(movingAverageType, MovingAverageType)
self.Name = '{}({},{},{},{},{})'.format(self.__class__.__name__, fastPeriod, slowPeriod, signalPeriod, movingAverageTypeString, resolutionString)
def Update(self, algorithm, data):
''' Determines an insight for each security based on it's current MACD signal
Args:
algorithm: The algorithm instance
data: The new data available
Returns:
The new insights generated'''
insights = []
for key, sd in self.symbolData.items():
if sd.Security.Price == 0:
continue
direction = InsightDirection.Flat
normalized_signal = sd.MACD.Signal.Current.Value / sd.Security.Price
if normalized_signal > self.bounceThresholdPercent:
direction = InsightDirection.Up
elif normalized_signal < -self.bounceThresholdPercent:
direction = InsightDirection.Down
# ignore signal for same direction as previous signal
if direction == sd.PreviousDirection:
continue;
insight = Insight.Price(sd.Security.Symbol, self.insightPeriod, direction)
sd.PreviousDirection = insight.Direction
insights.append(insight)
return insights
def OnSecuritiesChanged(self, algorithm, changes):
'''Event fired each time the we add/remove securities from the data feed.
This initializes the MACD for each added security and cleans up the indicator for each removed security.
Args:
algorithm: The algorithm instance that experienced the change in securities
changes: The security additions and removals from the algorithm'''
for added in changes.AddedSecurities:
self.symbolData[added.Symbol] = SymbolData(algorithm, added, self.fastPeriod, self.slowPeriod, self.signalPeriod, self.movingAverageType, self.resolution)
for removed in changes.RemovedSecurities:
data = self.symbolData.pop(removed.Symbol, None)
if data is not None:
# clean up our consolidator
algorithm.SubscriptionManager.RemoveConsolidator(removed.Symbol, data.Consolidator_15);
algorithm.SubscriptionManager.RemoveConsolidator(removed.Symbol, data.Consolidator_240);
class SymbolData:
def __init__(self, algorithm, security, fastPeriod, slowPeriod, signalPeriod, movingAverageType, resolution):
self.Security = security
self.MACD = MovingAverageConvergenceDivergence(fastPeriod, slowPeriod, signalPeriod, movingAverageType)
self.MACDTrend = MovingAverageConvergenceDivergence(fastPeriod, slowPeriod, signalPeriod, movingAverageType)
#self.Consolidator = algorithm.ResolveConsolidator(security.Symbol, resolution)
self.Consolidator_15 = QuoteBarConsolidator(15)
algorithm.RegisterIndicator(security.Symbol, self.MACD, self.Consolidator_15)
self.Consolidator_240 = QuoteBarConsolidator(240)
algorithm.RegisterIndicator(security.Symbol, self.MACDTrend, self.Consolidator_240)
self.PreviousDirection = Nonefrom 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.Algorithm.Framework import *
from QuantConnect.Algorithm.Framework.Alphas import *
from QuantConnect.Algorithm.Framework.Portfolio import *
from QuantConnect.Algorithm.Framework.Selection import *
from Alphas.ConstantAlphaModel import ConstantAlphaModel
from Execution.ImmediateExecutionModel import ImmediateExecutionModel
from Risk.MaximumDrawdownPercentPerSecurity import MaximumDrawdownPercentPerSecurity
from MACDMomentumAlphaModel import MacdMomentumAlphaModel
from datetime import timedelta
import numpy as np
### <summary>
### Basic template framework algorithm uses framework components to define the algorithm.
### </summary>
### <meta name="tag" content="using data" />
### <meta name="tag" content="using quantconnect" />
### <meta name="tag" content="trading and orders" />
class MACDMomentumFramework(QCAlgorithmFramework):
'''Basic template framework algorithm uses framework components to define the algorithm.'''
def Initialize(self):
'''
A function to define things to do at the start of the strategy
Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
'''
# universe selection
#self.failedSecurities = ["USDCAD"]
#self.symbols = ["EURUSD","EURAUD","GBPUSD","AUDUSD"]
#self.forex = self.AddForex(self.symbols[0], Resolution.Minute, Market.FXCM)
self.params = {'start_yr':2016,
'start_mth':1,
'start_day':1,
'end_yr':2018,
'end_mth':6,
'end_day':1,
'principal':25000,
'warmup':100,
'max_weight_per_pos':0.02,
'leverage':200,
'tp_atr_factor':2.5,
'sl_atr_factor':3.0,
'main_timeframe':15,
'trend_timeframe':240,
'kama_fast_period':5,
'kama_slow_period':30,
'adx_period':14,
'adxr_period':14,
'atr_period':14,
'macd_fast_period':12,
'macd_slow_period':26,
'macd_signal_period':9,
'lookback_win':5
}
self.SetStartDate(self.params['start_yr'], self.params['start_mth'], self.params['start_day']) #Set Start Date
self.SetEndDate(self.params['end_yr'], self.params['end_mth'], self.params['end_day']) #Set End Date
self.SetCash(self.params['principal']) #Set Strategy Cash
# Set requested data resolution
self.UniverseSettings.Resolution = Resolution.Minute
self.SetBrokerageModel(BrokerageName.FxcmBrokerage)
# Find more symbols here: http://quantconnect.com/data
# Forex, CFD, Equities Resolutions: Tick, Second, Minute, Hour, Daily.
# Futures Resolution: Tick, Second, Minute
# Options Resolution: Minute Only.
self.symbols = []
#curr = Currencies.CurrencyPairs
curr = ["EURUSD","GBPUSD","EURAUD","GBPNZD"]
for i in range(len(curr)):
self.Debug(curr[i])
self.symbols.append(Symbol.Create(curr[i], SecurityType.Forex, Market.FXCM))
# set algorithm framework models
self.SetUniverseSelection(ManualUniverseSelectionModel(self.symbols))
self.SetAlpha(MacdMomentumAlphaModel(12,26,9,MovingAverageType.Exponential, Resolution.Minute))
self.SetPortfolioConstruction(EqualWeightingPortfolioConstructionModel())
self.SetExecution(ImmediateExecutionModel())
self.SetRiskManagement(MaximumDrawdownPercentPerSecurity(0.01))
self.Debug("numpy test >>> print numpy.pi: " + str(np.pi))
def OnOrderEvent(self, orderEvent):
if orderEvent.Status == OrderStatus.Filled:
self.Debug("Purchased Stock: {0}".format(orderEvent.Symbol))