| 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