Overall Statistics
import numpy as np
from datetime import datetime, timedelta
from collections import deque
from decimal import Decimal
from itertools import groupby
from pytz import utc
UTCMIN = datetime.min.replace(tzinfo=utc)

from Risk.NullRiskManagementModel import NullRiskManagementModel


class BasicTemplateFrameworkAlgorithm(QCAlgorithmFramework):

    def Initialize(self):

        self.SetStartDate(2017, 1, 1)   #Set Start Date
        self.SetEndDate(2017, 1, 25)    #Set End Date
        self.SetCash(1000)           #Set Strategy Cash
        self.SetBrokerageModel(BrokerageName.OandaBrokerage,AccountType.Margin)
        self.resolution = Resolution.Daily

        self.UniverseSettings.Resolution = Resolution.Daily
        symbols = [Symbol.Create("EURUSD", SecurityType.Forex, Market.Oanda)
                   #,Symbol.Create("GBPUSD", SecurityType.Forex, Market.Oanda)
                   ]
        
        
        self.SetUniverseSelection( ManualUniverseSelectionModel(symbols) )
        
        self.SetAlpha(My_Alpha())
        
        self.SetPortfolioConstruction(MyPortfolio()) 
        
        self.SetExecution(NullExecutionModel())
        
        self.SetRiskManagement(NullRiskManagementModel())
    

    def OnOrderEvent(self, orderEvent):
        if orderEvent.Status == OrderStatus.Filled:
            # self.Debug("Purchased Stock: {0}".format(orderEvent.Symbol))
            pass
        
        
class My_Alpha(AlphaModel):
    def __init__(self):
        self.resolution = Resolution.Daily
        
        self.resolutionPrediction = Resolution.Hour
        self.expiryPeriod = 16
        self.predictionInterval = Time.Multiply(Extensions.ToTimeSpan(self.resolutionPrediction), self.expiryPeriod)
        
        self.Symbols = []
        
    def Update(self, algorithm, data):
        
        insights = []
        
        if algorithm.Time.strftime('%A') == "Thursday":
            for symbol in self.Symbols:
                insights.append(Insight.Price(symbol, self.predictionInterval, InsightDirection.Up, None, None))
                algorithm.Log( "Thursday Insight added "+ str(InsightDirection.Up))
                algorithm.Log( "predictionInterval: "+ str(self.predictionInterval))
        
        if algorithm.Time.strftime('%A') == "Friday":
            for symbol in self.Symbols:
                insights.append(Insight.Price(symbol, self.predictionInterval, InsightDirection.Up, None, None))
                algorithm.Log( "Friday Insight added "+ str(InsightDirection.Down))
                algorithm.Log( "predictionInterval: "+ str(self.predictionInterval))
        
        if algorithm.Time.strftime('%A') == "Monday":
            algorithm.Log( "Monday ")
            
        return insights
        
    def OnSecuritiesChanged(self, algorithm, changes):
        
        for removed in changes.RemovedSecurities:
            if removed in self.Symbols:
                self.Symbols.remove(removed)
            if removed.Symbol in self.insightsTimeBySymbol:
                self.insightsTimeBySymbol.pop(removed.Symbol)
        
        for symbol in changes.AddedSecurities:
            self.Symbols.append(symbol.Symbol)
            
class MyPortfolio(PortfolioConstructionModel):
    def __init__(self, resolution = Resolution.Daily):
        
        self.insightCollection = InsightCollection()
        self.removedSymbols = []
        self.nextExpiryTime = UTCMIN
        self.rebalancingTime = UTCMIN
        self.rebalancingPeriod = Extensions.ToTimeSpan(resolution)
        
    def CreateTargets(self, algorithm, insights):
        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])

        percent = 0.2

        errorSymbols = {}

        for insight in lastActiveInsights:
            target = PortfolioTarget.Percent(algorithm, insight.Symbol, insight.Direction * percent)
            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

        if self.nextExpiryTime > UTCMIN:
            algorithm.Log("Portfolio Targets: "+str([( str(x.Symbol) ,x.Quantity) for x in targets]))
            algorithm.Log("nextExpiryTime: "+str(self.nextExpiryTime))
        
        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)