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 = None
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.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))