Overall Statistics |
Total Trades 41 Average Win 0.00% Average Loss -0.01% Compounding Annual Return -1.644% Drawdown 0.300% Expectancy -0.957 Net Profit -0.279% Sharpe Ratio -6.562 Probabilistic Sharpe Ratio 0.000% Loss Rate 96% Win Rate 4% Profit-Loss Ratio 0.00 Alpha -0.011 Beta -0.006 Annual Standard Deviation 0.002 Annual Variance 0 Information Ratio -7.432 Tracking Error 0.056 Treynor Ratio 2.204 Total Fees $0.00 |
import decimal as d from System.Drawing import Color class MovingAverageBasic(QCAlgorithm): def Initialize(self): self.SetStartDate(2017,1,1) # Set Start Date self.SetEndDate(2017,3,1) self.SetCash(1000000) # Set Strategy Cash self.defaultQuantity = 100000 #self.AddForex("AUDUSD", Resolution.Hour, Market.Oanda) #AddForex merely adds the security, but you cant refer to it later. self.audusd = self.AddForex("AUDUSD", Resolution.Hour, Market.Oanda).Symbol #But doing this you now can refer to self.symbol # Symbols are a way to identify an asset uniquely. They are objects which contain all the information required # to identify a security, without needing external references, or proprietary database look-ups. self.SetBrokerageModel(BrokerageName.OandaBrokerage) self.fastEMA = self.EMA("AUDUSD", 10, Resolution.Hour) self.slowEMA = self.EMA("AUDUSD", 100, Resolution.Hour) self.fastEMAWin = RollingWindow[float](10) self.slowEMAWin = RollingWindow[float](10) self.PriceWin = RollingWindow[float](3) self.ATRindy = self.ATR("AUDUSD",20,MovingAverageType.Simple, Resolution.Hour) self.SetWarmUp(100) self.fill_price = 0 self.quant_filled = 0 #Risk Management self.leverage = self.Securities["AUDUSD"].Leverage self.pip = self.Securities["AUDUSD"].SymbolProperties.MinimumPriceVariation * 10 #times 10 converts pipette to pip #initializing charts #Chart.Stacked: This means the chart will appear as a separate chart below the main equity chart. #Chart.Overlay: This means that the chart will be overlayed on top of the main equity chart. FXPlot = Chart("FX Plot", ChartType.Stacked) # On the Trade Plotter Chart we want 3 series: trades and price: FXPlot.AddSeries(Series("Price", SeriesType.Line, 0)) FXPlot.AddSeries(Series("Buy", SeriesType.Scatter, '$', Color.Green, ScatterMarkerSymbol.Triangle)) FXPlot.AddSeries(Series("Sell", SeriesType.Scatter, '$', Color.Red, ScatterMarkerSymbol.TriangleDown)) FXPlot.AddSeries(Series("FastMA", SeriesType.Line, '$' , Color.Orange)) FXPlot.AddSeries(Series("SlowMA", SeriesType.Line, '$', Color.Purple)) self.AddChart(FXPlot) 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 ''' # Creates an indicator and adds to a rolling window when it is updated self.fastEMAWin.Add(self.fastEMA.Current.Value) self.slowEMAWin.Add(self.slowEMA.Current.Value) self.ATR_Now = self.ATRindy.Current.Value if not self.slowEMA.IsReady: return if not self.fastEMA.IsReady: return if self.IsWarmingUp: return #Logging------------------------------------------------------------------------------- Cutup = self.CrossAbove(self.fastEMAWin, self.slowEMAWin) Cutdown = self.CrossBelow(self.fastEMAWin, self.slowEMAWin) time_now = self.Time holdings = self.Securities["AUDUSD"].Holdings.Quantity if self.Portfolio[self.audusd].IsLong: if self.Falling(self.slowEMAWin, self.slowEMAWin): self.Liquidate(self.audusd) self.Log("Closing Long | Cutup is {} | Cutdown is {}".format(Cutup, Cutdown)) elif self.Portfolio[self.audusd].IsShort: if self.Rising(self.slowEMAWin, self.slowEMAWin): self.Liquidate(self.audusd) self.Log("Closing Short | Cutup is {} | Cutdown is {}".format(Cutup, Cutdown)) else: if self.CrossAbove(self.fastEMAWin, self.slowEMAWin) and not self.Falling(self.slowEMAWin, self.slowEMAWin): self.MarketOrder(self.audusd, self.CalculateTradeSize()) self.Log("New Long | Cutup is {} | Cutdown is {}".format(Cutup, Cutdown)) self.Log("Market long order fill price is {}".format(self.fill_price)) #insert calculation function here self.StopMarketOrder(self.audusd, -self.defaultQuantity, self.fill_price - 2*self.ATR_Now ) #self.holdings = self.Securities["AUDUSD"].Holdings.Quantity if self.CrossBelow(self.fastEMAWin, self.slowEMAWin) and not self.Rising(self.slowEMAWin, self.slowEMAWin): self.MarketOrder(self.audusd, -self.defaultQuantity) self.Log("New Short | Cutup is {} | Cutdown is {}".format(Cutup, Cutdown)) self.Log("Market short order fill price is {}".format(self.fill_price)) #insert calculation function here self.StopMarketOrder(self.audusd, self.defaultQuantity, self.fill_price + 2*self.ATR_Now ) #self.holdings = self.Securities["AUDUSD"].Holdings.Quantity #below is all for the charting self.Plot("FX Plot", "FastMA", self.fastEMA.Current.Value) self.Plot("FX Plot", "SlowMA", self.slowEMA.Current.Value) self.Plot("FX Plot","Price", data["AUDUSD"].Price) #below are event handlers, as well as functions to determine the status of the EMA #------------------------------------------------------------------------------- def CrossAbove(self, fast, slow, tolerance=0): return fast[0] > slow[0] * (1 + tolerance) and fast[2] < slow[2] * (1 - tolerance) def CrossBelow(self, fast, slow, tolerance = 0): return fast[0] < slow[0] * (1 - tolerance) and fast[2] > slow[2] * (1 + tolerance) def Rising(self, current, lookback, tolerance = 0): return current[0] > lookback[2] * (1 + tolerance) def Falling(self, current, lookback, tolerance = 0): return current[0] < lookback[2] * (1 - tolerance) def CalculateTradeSize(self): self.MaxLossAbsolute = self.Portfolio.Cash * 0.02 self.MaxLossAbsolute + 2*self.ATR_Now return self.MaxLossAbsolute / 2 * self.ATR_Now def OnOrderEvent(self, orderEvent): self.order_tick = self.Transactions.GetOrderById(orderEvent.OrderId) self.fill_price = orderEvent.FillPrice self.quant_filled = orderEvent.FillQuantity if self.fill_price > 0: if self.quant_filled > 0: self.Plot("FX Plot","Buy",self.fill_price) elif self.quant_filled <0: self.Plot("FX Plot","Sell",self.fill_price) #self.Log("An order was filled at {}".format(self.fill_price))