| Overall Statistics |
|
Total Trades 593 Average Win 1.86% Average Loss -2.46% Compounding Annual Return -7.120% Drawdown 52.300% Expectancy -0.033 Net Profit -32.463% Sharpe Ratio -0.166 Probabilistic Sharpe Ratio 0.331% Loss Rate 45% Win Rate 55% Profit-Loss Ratio 0.76 Alpha -0.117 Beta 0.758 Annual Standard Deviation 0.249 Annual Variance 0.062 Information Ratio -0.666 Tracking Error 0.211 Treynor Ratio -0.055 Total Fees $615.39 |
import numpy as np
import pandas as pd
from datetime import datetime, timedelta
class UncoupledTransdimensionalAntennaArray(QCAlgorithm):
def Initialize(self):
stopMarketTicket = None
stopMarketFillTime = datetime.min
highestPrice = 0
self.SetStartDate(2015, 1, 1) # Set Start Date
self.SetCash(10000) # Set Strategy Cash
self.asset = self.AddEquity("ZIV", Resolution.Minute)
self.asset.SetDataNormalizationMode(DataNormalizationMode.Raw)
# define the n period indicators with indicator constructors.
self.rocfiveDay = RateOfChange(5)
self.rocfiveDay.Updated += self.ROCFiveDayUpdated
self.rocfiveDayWindow = RollingWindow[IndicatorDataPoint](6)
# for volatility.
self.roc1 = RateOfChange(1)
# for stop loss
self.atr = AverageTrueRange(20)
# this is for listening to order status
self.lastOrderEvent = None
self.ticket = None # Flag for position status
# define portfolio volatility
self.target_portfolio_sigma = 0.25
self.Schedule.On(self.DateRules.EveryDay("ZIV"), self.TimeRules.BeforeMarketClose("ZIV", 5), self.Rebalance)
def Rebalance(self):
# this is to warm up indicators.
if not self.rocfiveDay.IsReady:
history = self.History("ZIV", 5, Resolution.Daily)
for bar in history:
self.rocfiveDay.Update(bar.EndTime, bar.Close)
self.rocfiveDay.Update(self.Time, self.Securities["ZIV"].Close)
# wait is indicators are not ready.
if not self.rocfiveDayWindow.IsReady:
return
# voltaility calculator. one day return.
if not self.roc1.IsReady:
history = self.History("ZIV", 1, Resolution.Daily)
for bar in history:
self.roc1.Update(bar.EndTime, bar.Close)
self.roc1.Update(self.Time, self.Securities["ZIV"].Close)
self.std = IndicatorExtensions.Of(StandardDeviation(30), self.roc1)
'''
# ATR for Stop Loss.
if not self.atr.IsReady:
history = self.History("ZIV", 20, Resolution.Daily)
for bar in history:
self.atr.Update(bar.EndTime, bar.Close)
self.atr.Update(self.Time, self.Securities["ZIV"].Close)
'''
long_signal_1 = self.rocfiveDayWindow[0] > self.rocfiveDayWindow[1]
if not self.Portfolio.Invested:
if long_signal_1 == True:
volatility = self.std.Current.Value * np.sqrt(252) # get vol.
self.Debug("Volatility " + str(volatility))
weight = self.target_portfolio_sigma / volatility # get weight.
#quantity = (self.Portfolio.TotalPortfolioValue * weight)/self.Securities["ZIV"].Close # get quantity.
quantity = self.Portfolio.TotalPortfolioValue / self.Securities["ZIV"].Close
self.ticket = self.MarketOrder("ZIV", quantity) #self.MarketOrder("ZIV", quantity)
self.stopMarketTicket = self.StopMarketOrder("ZIV", -quantity, 0.9 * self.Securities["ZIV"].Close) ## TODO update to 2 times ATR
self.Debug("Volatility " + str(volatility))
self.Debug("Portfolio Size " + str(self.Portfolio.TotalPortfolioValue ))
self.Debug("Quantity " + str(quantity))
# self.Log() # add log messaging
elif self.ticket is not None and (self.UtcTime - self.ticket.Time).days < 3: ## to update stop loss.
if self.Securities["ZIV"].Close > self.highestPrice:
self.highestPrice = self.Securities["ZIV"].Close # save the new highestPrice
updateFields = UpdateOrderFields()
updateFields.StopPrice = self.highestPrice * 0.9 # TODO self.highestPrice - 2 * self.atr.Current.Value ## updating stop price
self.stopMarketTicket.Update(updateFields)
self.Debug("ZIV: " + str(self.highestPrice) + " Stop: " + str(updateFields.StopPrice))
elif self.ticket is not None and self.UtcTime >= self.ticket.Time + timedelta(days = 3):
self.Liquidate("ZIV")
self.highestPrice = 0
self.ticket = None
def ROCFiveDayUpdated(self, sender, updated):
self.rocfiveDayWindow.Add(updated)