Overall Statistics
Total Trades
114
Average Win
4.44%
Average Loss
-1.99%
Compounding Annual Return
34.064%
Drawdown
22.400%
Expectancy
0.248
Net Profit
26.020%
Sharpe Ratio
1.037
Loss Rate
61%
Win Rate
39%
Profit-Loss Ratio
2.23
Alpha
0.259
Beta
0.102
Annual Standard Deviation
0.271
Annual Variance
0.073
Information Ratio
0.24
Tracking Error
0.292
Treynor Ratio
2.741
Total Fees
$3420.00
import decimal

class FCPODT(QCAlgorithm):

    def Initialize(self): 
        self.SetStartDate(2019, 1, 1)  # Set Start Date
        self.SetEndDate(2019, 12, 31)  # Set End Date
        self.SetCash(25000)  # Set Strategy Cash
        #self.SetBrokerageModel(BrokerageName.Default, AccountType.Margin)
        self.fcpo = self.AddData(Fcpo, "FCPO", Resolution.Minute)
        self.syl = self.fcpo.Symbol
        self.fcpo.SymbolProperties.MinimumPriceVariation  = 1
        self.fcpo.SymbolProperties.LotSize  = 1
        self.fcpo.SymbolProperties.QuoteCurrency   = "MYR"
        self.fcpo.SymbolProperties.ContractMultiplier    = 25
        self.fcpo.SetLeverage(4)
        #self.fcpo.SecurityType = Securities.Future
        #self.fcpo.MarginModel = FutureMarginModel(1)#BuyingPowerModel(25,1)
        #self.fcpo.Holdings
        
        self.Consolidate(self.syl, timedelta(minutes=30), self.OnDataConsolidated)
        self.Consolidate(self.syl, timedelta(days=1), self.OnDayConsolidated)
        self.selltrig = None
        self.buytrig = None
        self.exitselltrig = None
        self.exitbuytrig = None
        self.currentopen = None
        self.dailyBarWindow = RollingWindow[TradeBar](3)
        #self.hist_df = self.History([self.syl.Value], TimeSpan.FromDays(3), Resolution.Daily)
        #self.SetWarmUp(TimeSpan.FromDays(3), Resolution.Daily)
        
        
        
        
        
        self.fcpo.FeeModel = ConstantFeeModel(30)
    
    def OnDayConsolidated(self,bar):
        #self.Debug(self.Time)
        #self.Debug(bar.Time)
        #self.Debug(bar)
        self.dailyBarWindow.Add(bar)
        
    def OnDataConsolidated(self,bar):
        k1 = 0.5
        k2 = 0.5
        
        if bar.Time.hour == 10 and bar.Time.minute == 30:
            # Save the first bar of the trading day 
            self.currentopen = bar 
            
            if self.dailyBarWindow.IsReady:
                HH = max([self.dailyBarWindow[0].High,self.dailyBarWindow[1].High,self.dailyBarWindow[2].High])
                HC = max([self.dailyBarWindow[0].Close,self.dailyBarWindow[1].Close,self.dailyBarWindow[2].Close])
                LC = min([self.dailyBarWindow[0].Close,self.dailyBarWindow[1].Close,self.dailyBarWindow[2].Close])
                LL = min([self.dailyBarWindow[0].Low,self.dailyBarWindow[1].Low,self.dailyBarWindow[2].Low])
                #self.Debug('hh:{} hl:{} lh:{} ll:{}'.format(hh,hc,lc,ll))
                #self.Debug('self.Time:{}, 0:{}, 1:{} 2:{}'.format(self.Time, self.dailyBarWindow[0].Time, self.dailyBarWindow[1].Time, self.dailyBarWindow[2].Time))
                if (HH - LC) >= (HC - LL):
                    signalrange = HH - LC
                else:
                    signalrange = HC - LL
        
                self.selltrig = self.currentopen.Open - decimal.Decimal(k2) * signalrange
                self.buytrig = self.currentopen.Open + decimal.Decimal(k1) * signalrange
                self.exitselltrig = self.currentopen.Open + decimal.Decimal(0.40) * signalrange
                self.exitbuytrig = self.currentopen.Open - decimal.Decimal(0.40) * signalrange
                
            else:
                self.selltrig = None
                self.buytrig = None
                
        
    def OnData(self, data):
        '''OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
            Arguments:
                data: Slice object keyed by symbol containing the stock data
        '''

        # if not self.Portfolio.Invested:
        #    self.SetHoldings("SPY", 1)
        #self.Plot('Close', 'Closing Price', data[self.syl].Close)
        if not self.dailyBarWindow.IsReady or not self.buytrig or not self.selltrig:
            return
        
        holdings = self.Portfolio[self.syl].Quantity
        
        if holdings == 0:
            if data[self.syl].High >= self.buytrig:
                self.MarketOrder(self.syl,1)
            elif data[self.syl].Low <= self.selltrig:
                self.MarketOrder(self.syl,-1)
        elif holdings > 0:
            if data[self.syl].Low <= self.exitbuytrig:
                self.Liquidate()
        elif holdings < 0:
            if data[self.syl].High >= self.exitselltrig:
                self.Liquidate()
        
        '''
        if self.Portfolio[self.syl].Price >= self.buytrig:
            if holdings >= 0:
                if holdings == 0:
                    #self.SetHoldings(self.syl, 1)
                    self.MarketOrder(self.syl,1)
                    self.Log("Buy open: "+ str(self.currentopen.Open)+" buy: "+str(self.buytrig))
            else:
                #self.Liquidate(self.syl)
                #self.SetHoldings(self.syl, 1)
                self.MarketOrder(self.syl,1)
                self.Log("Exit Sell open: "+ str(self.currentopen.Open)+" buy: "+str(self.buytrig))
                
                
        elif self.Portfolio[self.syl].Price < self.selltrig:
             if holdings > 0:
                #self.Liquidate(self.syl)
                #self.SetHoldings(self.syl, -1)
                self.MarketOrder(self.syl,-1)
                self.Log("Exit Buy open: "+ str(self.currentopen.Open)+" sell: "+str(self.selltrig))
             else:
                if holdings == 0:
                    #self.SetHoldings(self.syl, -1)
                    self.MarketOrder(self.syl,-1)
                    self.Log("Sell open: "+ str(self.currentopen.Open)+" sell: "+str(self.selltrig))
                
        #self.Log("open: "+ str(self.currentopen.Open)+" buy: "+str(self.buytrig)+" sell: "+str(self.selltrig))
        '''
    def OnOrderEvent(self, orderEvent):
        if orderEvent.Status != OrderStatus.Filled:
            return
        
        
class Fcpo(PythonData):
    
    '''Fcpo Custom Data Class'''
    def GetSource(self, config, date, isLiveMode):
        return SubscriptionDataSource("https://www.dropbox.com/s/ivtywe3avc4m1mn/fcpo.csv?dl=1", SubscriptionTransportMedium.RemoteFile)


    def Reader(self, config, line, date, isLiveMode):
        if not (line.strip() and line[0].isdigit()): return None

        # New Nifty object
        index = Fcpo()
        index.Symbol = config.Symbol

        try:
            # Example File Format:
            # Date,       Open       High        Low       Close     Volume
            # 2011-09-13  7792.9    7799.9     7722.65    7748.7    116534670
            data = line.split(',')
            d = datetime.strptime(data[0], "%Y%m%d")
            t = datetime.strptime(data[1], "%H%M").time()
            #index.Time = datetime.strptime(data[0], "%Y%m%d")
            index.Time = datetime.combine(d, t)
            index.Value = data[5]
            index["Open"] = float(data[2])
            index["High"] = float(data[3])
            index["Low"] = float(data[4])
            index["Close"] = float(data[5])
            index["Volume"] = float(data[6])


        except ValueError:
                # Do nothing
                return None

        return index