Overall Statistics |
Total Trades 294 Average Win 0.09% Average Loss -0.05% Compounding Annual Return 1.956% Drawdown 4.800% Expectancy 0.506 Net Profit 3.456% Sharpe Ratio 0.44 Loss Rate 48% Win Rate 52% Profit-Loss Ratio 1.87 Alpha -0.018 Beta 2.124 Annual Standard Deviation 0.037 Annual Variance 0.001 Information Ratio 0.005 Tracking Error 0.037 Treynor Ratio 0.008 Total Fees $0.00 |
from datetime import datetime, timedelta import numpy as np import pandas as pd from decimal import Decimal from System.Drawing import Color # https://www.investoo.com/pivot-breakout-forex-strategy/ class SvePivotsAlgorithm(QCAlgorithm): def Initialize(self): self.SetStartDate(2017, 1, 1) self.SetEndDate(2018, 10, 1) self.SetCash(10000) self.symbol = self.AddForex("EURUSD", Resolution.Minute, Market.Oanda).Symbol self.pivot = SvePivots(1) self.SetWarmUp(timedelta(2)) dailyConsolidator = QuoteBarConsolidator(timedelta(1)) dailyConsolidator.DataConsolidated += self.DailyBarHandler self.SubscriptionManager.AddConsolidator(self.symbol, dailyConsolidator) self.RegisterIndicator(self.symbol, self.pivot, dailyConsolidator) fiveMinuteConsolidator = QuoteBarConsolidator(timedelta(minutes=5)) dailyConsolidator.DataConsolidated += self.fiveMinuteBarHandler self.SubscriptionManager.AddConsolidator(self.symbol, fiveMinuteConsolidator) self.Schedule.On(self.DateRules.EveryDay(self.symbol), self.TimeRules.AfterMarketOpen(self.symbol, 1), self.EveryDayAfterMarketOpen) self.bars = RollingWindow[QuoteBar](2) self.state = None plot = Chart("PivotPlot") for i in ["S1","S2","S3","R1","R2","R3"]: plot.AddSeries(Series(i, SeriesType.Line, 0)) plot.AddSeries(Series("PP", SeriesType.Line, '$', Color.Red)) plot.AddSeries(Series("Price", SeriesType.Line, '$', Color.Blue)) self.AddChart(plot) def OnData(self, data): pass def EveryDayAfterMarketOpen(self): # establish the market state bias for the day after the market open # the bias for the day is bullish if the price action opens for the trading day above the central pivot point if self.Securities[self.symbol].Price > self.pivot.PP: self.state = True # the bias for the day is bearish if the price action opens for the trading day below the central pivot point if self.Securities[self.symbol].Price < self.pivot.PP: self.state = False def DailyBarHandler(self, sender, bar): self.Plot("PivotPlot", 'S1', self.pivot.S1) self.Plot("PivotPlot", 'S2', self.pivot.S2) self.Plot("PivotPlot", 'S3', self.pivot.S3) self.Plot("PivotPlot", 'R1', self.pivot.R1) self.Plot("PivotPlot", 'R2', self.pivot.R2) self.Plot("PivotPlot", 'R3', self.pivot.R3) self.Plot("PivotPlot", 'PP', self.pivot.PP) self.Plot("PivotPlot", 'Price', self.Securities[self.symbol].Price) def fiveMinuteBarHandler(self, sender, bar): ''' When the price action eventually breaks out of one boundary, use the principles of the breakout trade to make the entry and use the next pivot point in the path of the price action as the profit target, while setting a stop loss below the broken pivot (long trade) or above the broken pivot (short trade). ''' if self.IsWarmingUp or not self.pivot.IsReady: return self.bars.Add(bar) if not self.bars.IsReady: return # Be bullish when the price is above the main pivot point if self.state: # trip from below to above R1 if self.bars[1].High < self.pivot.R1 < self.bars[0].High: self.MarketOrder(self.symbol, 1000) self.LimitOrder(self.symbol, -1000, self.pivot.R2) self.StopMarketOrder(self.symbol, -1000, self.pivot.R1-Decimal(0.00500)) # trip from below to above R2 if self.bars[1].High < self.pivot.R2 < self.bars[0].High: self.Transactions.CancelOpenOrders(self.symbol) self.MarketOrder(self.symbol, 1000) self.LimitOrder(self.symbol, -1000, self.pivot.R3) self.StopMarketOrder(self.symbol, -1000, self.pivot.R2-Decimal(0.00500)) # Be bearish when the price is below the main pivot point if not self.state: # trip from above to below S1 if self.bars[0].Low < self.pivot.S1 < self.bars[1].Low: self.MarketOrder(self.symbol, -1000) self.LimitOrder(self.symbol, 1000, self.pivot.S2) self.StopMarketOrder(self.symbol, 1000, self.pivot.S1+Decimal(0.00500)) # trip from above to below S2 if self.bars[0].Low < self.pivot.S2 < self.bars[1].Low: self.Transactions.CancelOpenOrders(self.symbol) self.MarketOrder(self.symbol, -1000) self.LimitOrder(self.symbol, 1000, self.pivot.S3) self.StopMarketOrder(self.symbol, 1000, self.pivot.S2+Decimal(0.00800)) class SvePivots: def __init__(self, period): self.Time = datetime.min self.PP = None self.R1 = self.R2 = self.R3 = None self.S1 = self.S2 = self.S3 = None self.RM1 = self.RM2 = self.RM3 = None self.SM1 = self.SM2 = self.SM3 = None self.PH = self.PL = None self.IsReady = False def Update(self, input): self.Time = input.EndTime self.PP = (input.High + input.Low + input.Close) / Decimal(3) # Pivot point self.R1 = self.PP*Decimal(2) - input.Low # Resistance 1 self.R2 = self.PP + (input.High - input.Low) # Resistance 2 self.R3 = self.PP*Decimal(2) + (input.High - input.Low*Decimal(2)) # Resistance 3 self.S1 = self.PP*Decimal(2) - input.High # Support 1 self.S2 = self.PP - (input.High - input.Low) # Support 2 self.S3 = self.PP*Decimal(2) - (input.High*Decimal(2) - input.Low) # Support 3 self.RM1 = (self.R1-self.PP)/Decimal(2) + self.PP # Resistance Mean value 1 self.RM2 = (self.R2-self.R1)/Decimal(2) + self.R1 # Resistance Mean value 2 self.RM3 = (self.R3-self.R2)/Decimal(2) + self.R2 # Resistance Mean value 3 self.SM1 = (self.PP-self.S1)/Decimal(2) + self.S1 # Support Mean value 1 self.SM2 = (self.S1-self.S2)/Decimal(2) + self.S2 # Support Mean value 2 self.SM3 = (self.S2-self.S3)/Decimal(2) + self.S3 # Support Mean value 3 self.PH = input.High # Previous day’s high self.PL = input.Low # Previous day’s low self.IsReady = self.PP is not None