Overall Statistics |
Total Trades 90 Average Win 1.37% Average Loss -0.23% Compounding Annual Return 1006.353% Drawdown 12.600% Expectancy 5.358 Net Profit 107.824% Sharpe Ratio 13.016 Probabilistic Sharpe Ratio 96.266% Loss Rate 8% Win Rate 92% Profit-Loss Ratio 5.94 Alpha 6.73 Beta -1.754 Annual Standard Deviation 0.522 Annual Variance 0.272 Information Ratio 12.799 Tracking Error 0.534 Treynor Ratio -3.875 Total Fees $0.00 Estimated Strategy Capacity $9700000.00 |
from AlgoToolbox import AlgoToolbox ''' To use this library place this at the top: from StrategyFxScalper import StrategyFxScalper Then instantiate the function: StrategyFxScalpCustom(StrategyFxScalper): ... startegy = StrategyFxScalpCustom() strategy.Run(data) ''' # ******************************** class StrategyFxScalper: # ******************************** # ------------------------------------------------------------------------------------------------------------- def __init__(self, qcAlgo, fxGalaxy, resolution, anchor_resolution, scalp_period, anchor_period, show_debug, show_log, anchor_slots): #, trade_units): # ------------------------------------------------------------------------------------------------------------- self.buy_flag = 0 self.sell_flag = 0 self.limitOrderTicket = None self.profitTargetOrderTicket = None self.stopLossOrderTicket = None self.scalp_ema_fast = 0 self.scalp_ema_slow = 0 self.anchor_ema_fast = 0 self.anchor_ema_slow = 0 self.qcAlgo = qcAlgo self.fxGalaxy = fxGalaxy self.BrickData = {} self.fxHoldingCoeff = 1 / len(fxGalaxy) self.resolution = resolution self.anchorResolution = anchor_resolution self.scalp_period = scalp_period self.anchor_period = anchor_period self.anchor_max_slots = anchor_slots #self.trade_units_amount = trade_units self.holding_value = 0 self.showDebug = show_debug self.showLog = show_log self.toolbox = AlgoToolbox(self.qcAlgo, self.showDebug, self.showLog) # ------------------------------------------------------------------------------------------------------------- def Run(self, data, scalp_call = False, anchor_call = False): # ------------------------------------------------------------------------------------------------------------- # validation # exit if warming up if self.qcAlgo.IsWarmingUp: return # init ctxData = data if ctxData is None: ctxData = self.BrickData # loop through all currencies in the galaxy for fxStarBrick in self.fxGalaxy.values(): # assign current strategy fxStarBrick.strategy = self # debug if needed if self.showDebug: if scalp_call or anchor_call: # debug for scalp/anchor live calls only! if fxStarBrick.IsChartHour(ctxData.Time): # debug for the chart time only self.debugRunFx(ctxData, fxStarBrick) # save brick data msg_no_brick_data = "No data for " + fxStarBrick.symbol.Value + "!!! Stop Run-Workflow ..."; err_no_brick_data = "ERROR: No data for " + fxStarBrick.symbol.Value + "!!! Stop Run-Workflow. Error-Message: "; data_exists = ctxData.ContainsKey(fxStarBrick.symbol) if data_exists: #try: self.BrickData = ctxData # live-run strategy for actual currency (live) if not scalp_call and not anchor_call: self.RunFx(ctxData, fxStarBrick) # live-run strategy for actual currency (scalp period) if allowed if scalp_call: self.RunFxScalp(ctxData, fxStarBrick) # live-run strategy for actual currency (anchor period) if allowed if anchor_call: self.RunFxAnchor(ctxData, fxStarBrick) #except: # # EXIT IF NO SYMBOL-DATA!!! # self.apriori_debug(err_no_brick_data + sys.exc_info()[0]) # self.apriori_log(err_no_brick_data + sys.exc_info()[0]) # return else: # EXIT IF NO SYMBOL-DATA!!! self.apriori_log(msg_no_brick_data) self.apriori_debug(msg_no_brick_data) return # ------------------------------------------------------------------------------------------------------------- def RunScalp(self, fxBrick): # ------------------------------------------------------------------------------------------------------------- # validation # exit if warming up if self.qcAlgo.IsWarmingUp: return # go! self.RunFxScalp(self.BrickData, fxBrick) # ------------------------------------------------------------------------------------------------------------- def RunAnchor(self, fxBrick): # ------------------------------------------------------------------------------------------------------------- # validation # exit if warming up if self.qcAlgo.IsWarmingUp: return # go! self.RunFxAnchor(self.BrickData, fxBrick) # base (override in custom) # ------------------------------------------------------------------------------------------------------------- def RunFx(self, data, fxBrick): # ------------------------------------------------------------------------------------------------------------- # init fxBrick.UpdateScalpFluentData(data) fxBrick.UpdateAnchorFluentData(data) # go! pass # base (override in custom) # ------------------------------------------------------------------------------------------------------------- def RunFxScalp(self, data, fxBrick): # ------------------------------------------------------------------------------------------------------------- # debug if needed if self.showDebug: self.debugRunFx(data, fxBrick) # init fxBrick.ResetScalpFluentData() # go! # check trades self.CheckTradeRules(data, fxBrick) # ------------------------------------------------------------------------------------------------------------- def CheckTradeRules(self, data, fxBrick): # ------------------------------------------------------------------------------------------------------------- fxBrick.Check_Trade_Rules(data) # base (override in custom) # ------------------------------------------------------------------------------------------------------------- def RunFxAnchor(self, data, fxBrick): # ------------------------------------------------------------------------------------------------------------- # debug if needed if self.showDebug: self.debugRunFx(data, fxBrick) # init fxBrick.ResetAnchorFluentData() fxBrick.AnchorIsWarmedUp() # go! pass # **************************************************** # * TRADE RULES REGION (BASE / BEGIN) * # **************************************************** # ------------------------------------------------------------------------------------------------------------- def OnTrigger_Long(self, data, fxBrick): # ------------------------------------------------------------------------------------------------------------- pass # TODO 1: Execute Rule # TODO 2: Plot Data if executed # ------------------------------------------------------------------------------------------------------------- def OnTrigger_Short(self, data, fxBrick): # ------------------------------------------------------------------------------------------------------------- pass # TODO 1: Execute Rule # TODO 2: Plot Data if executed # ------------------------------------------------------------------------------------------------------------- def OnTriggerDrop_Long(self, data, fxBrick): # ------------------------------------------------------------------------------------------------------------- pass # TODO 1: Execute Rule # TODO 2: Plot Data if executed # ------------------------------------------------------------------------------------------------------------- def OnTriggerDrop_Short(self, data, fxBrick): # ------------------------------------------------------------------------------------------------------------- pass # TODO 1: Execute Rule # TODO 2: Plot Data if executed # ------------------------------------------------------------------------------------------------------------- def OnEntry_Long(self, data, fxBrick): # ------------------------------------------------------------------------------------------------------------- pass # TODO 1: Execute Rule # TODO 2: Plot Data if executed # ------------------------------------------------------------------------------------------------------------- def OnEntry_Short(self, data, fxBrick): # ------------------------------------------------------------------------------------------------------------- pass # TODO 1: Execute Rule # TODO 2: Plot Data if executed # ------------------------------------------------------------------------------------------------------------- def OnEntry_Short(self, data, fxBrick): # ------------------------------------------------------------------------------------------------------------- pass # TODO 1: Execute Rule # TODO 2: Plot Data if executed # ------------------------------------------------------------------------------------------------------------- def OnExit_Long(self, data, fxBrick): # ------------------------------------------------------------------------------------------------------------- pass # TODO 1: Execute Rule # TODO 2: Plot Data if executed # ------------------------------------------------------------------------------------------------------------- def OnExit_Short(self, data, fxBrick): # ------------------------------------------------------------------------------------------------------------- pass # TODO 1: Execute Rule # TODO 2: Plot Data if executed # ------------------------------------------------------------------------------------------------------------- def OnStopLossAndTakeProfit_Long(self, data, fxBrick): # ------------------------------------------------------------------------------------------------------------- pass # TODO 1: Execute Rule # TODO 2: Plot Data if executed # ------------------------------------------------------------------------------------------------------------- def OnStopLossAndTakeProfit_Short(self, data, fxBrick): # ------------------------------------------------------------------------------------------------------------- pass # TODO 1: Execute Rule # TODO 2: Plot Data if executed # ------------------------------------------------------------------------------------------------------------- def OnFinishTrade_Long(self, data, fxBrick): # ------------------------------------------------------------------------------------------------------------- pass # TODO 1: Execute Rule # TODO 2: Plot Data if executed # ------------------------------------------------------------------------------------------------------------- def OnFinishTrade_Short(self, data, fxBrick): # ------------------------------------------------------------------------------------------------------------- pass # TODO 1: Execute Rule # TODO 2: Plot Data if executed # ------------------------------------------------------------------------------------------------------------- def OnStopLoss_Long(self, data, fxBrick): # ------------------------------------------------------------------------------------------------------------- pass # TODO 1: Execute Rule # TODO 2: Plot Data if executed # ------------------------------------------------------------------------------------------------------------- def OnStopLoss_Short(self, data, fxBrick): # ------------------------------------------------------------------------------------------------------------- pass # TODO 1: Execute Rule # TODO 2: Plot Data if executed # ------------------------------------------------------------------------------------------------------------- def OnTradeContinue_Long(self, data, fxBrick): # ------------------------------------------------------------------------------------------------------------- pass # TODO 1: Execute Rule # TODO 2: Plot Data if executed # ------------------------------------------------------------------------------------------------------------- def OnTradeContinue_Short(self, data, fxBrick): # ------------------------------------------------------------------------------------------------------------- pass # TODO 1: Execute Rule # TODO 2: Plot Data if executed # **************************************************** # * TRADE RULES REGION TRADE RULES (BASE / END) * # **************************************************** # ****************************************************** # * TRADE-ACTION RULES REGION TRADE RULES (BASE / BEGIN) * # ****************************************************** # ------------------------------------------------------------------------------------------------------------- def OnTradeOpen_Long_Holdings(self, data, fxBrick): # ------------------------------------------------------------------------------------------------------------- if self.qcAlgo.emit_trades: # init fxBrick.trade_action("OPEN_LONG") # BUY via SetHoldings() self.holding_value = 1 * self.qcAlgo.forex_leverage * self.qcAlgo.cash_max_ratio * fxBrick.weight self.qcAlgo.SetHoldings(fxBrick.symbol, self.holding_value) fxBrick.Emit_Insight() # TODO 1: Execute Rule # TODO 2: Plot Data if executed # ------------------------------------------------------------------------------------------------------------- def OnTradeOpen_Long(self, data, fxBrick, set_limits=True): # ------------------------------------------------------------------------------------------------------------- if self.qcAlgo.emit_trades: # reset limits fxBrick.reset_limits() # !!! prevent initial canceling of the limit orders !!! #fxBrick.veto_cancel_orders() # init fxBrick.trade_action("OPEN_LONG") price = fxBrick.data.Close # set absolute open level fxBrick.trade_abs_start_level = price fxBrick.trade_abs_stop_level = 0 # BUY via order (LONG) # get holgig coeffitient self.holding_value = 1 * self.qcAlgo.forex_leverage * self.qcAlgo.cash_max_ratio * fxBrick.weight # get weighted rounded quantity quantity = (self.qcAlgo.Portfolio.Cash / price) * self.holding_value rounded_quantity = fxBrick.GetRoundedOrderSize(quantity) # place long order (buy) self.qcAlgo.Buy(fxBrick.symbol, rounded_quantity) if set_limits: # calc by PIP rounde price take_profit = self.pip_round(fxBrick.trade_take_profit) stop_loss = self.pip_round(fxBrick.stop_loss_level) # take profit long fxBrick.ProfitTarget = self.qcAlgo.LimitOrder(fxBrick.symbol, -rounded_quantity, take_profit) # stop loss long fxBrick.StopLoss = self.qcAlgo.StopMarketOrder(fxBrick.symbol, -rounded_quantity, stop_loss) fxBrick.Emit_Insight() # TODO 1: Execute Rule # TODO 2: Plot Data if executed # ------------------------------------------------------------------------------------------------------------- def OnTradeClose_Long(self, data, fxBrick, closeRatio = 1): # closeRatio = 1 - close all holdings, 0.5 - close 50% of holdings, 0 - nothing to close # ------------------------------------------------------------------------------------------------------------- # avoid part closing on 1. exit (part-close) if closeRatio < 1 and not self.qcAlgo.exit_1_close: return # init price = fxBrick.data.Close # set absolute open level fxBrick.trade_abs_stop_level = price if self.qcAlgo.emit_trades: # close trade on given ratio fxBrick.trade_action("CLOSE_LONG_" + str(closeRatio * 100) + "_PERCENT") self.trade_close(data, fxBrick, closeRatio) fxBrick.Emit_Insight() # TODO 1: Execute Rule # TODO 2: Plot Data if executed # ------------------------------------------------------------------------------------------------------------- def OnTradeOpen_Short_Holdings(self, data, fxBrick): # ------------------------------------------------------------------------------------------------------------- if self.qcAlgo.emit_trades: fxBrick.trade_action("OPEN_SHORT") # SELL via SetHoldings() self.holding_value = -1 * self.qcAlgo.forex_leverage * self.qcAlgo.cash_max_ratio * fxBrick.weight self.qcAlgo.SetHoldings(fxBrick.symbol, self.holding_value) fxBrick.Emit_Insight() # TODO 1: Execute Rule # TODO 2: Plot Data if executed # ------------------------------------------------------------------------------------------------------------- def OnTradeOpen_Short(self, data, fxBrick, set_limits=True): # ------------------------------------------------------------------------------------------------------------- if self.qcAlgo.emit_trades: # reset limits fxBrick.reset_limits() # !!! prevent initial canceling of the limit orders !!! #fxBrick.veto_cancel_orders() # init fxBrick.trade_action("OPEN_SHORT") price = fxBrick.data.Close # set absolute open level fxBrick.trade_abs_start_level = price fxBrick.trade_abs_stop_level = 0 # SELL via order (SHORT) # get holgig coeffitient self.holding_value = self.qcAlgo.forex_leverage * self.qcAlgo.cash_max_ratio * fxBrick.weight # get weighted rounded quantity quantity = (self.qcAlgo.Portfolio.Cash / price) * self.holding_value rounded_quantity = fxBrick.GetRoundedOrderSize(quantity) # place short order (sell) self.qcAlgo.Sell(fxBrick.symbol, rounded_quantity) if set_limits: # calc by PIP rounde price take_profit = self.pip_round(fxBrick.trade_take_profit) stop_loss = self.pip_round(fxBrick.stop_loss_level) # take profit short fxBrick.ProfitTarget = self.qcAlgo.LimitOrder(fxBrick.symbol, rounded_quantity, take_profit) # stop loss short fxBrick.StopLoss = self.qcAlgo.StopMarketOrder(fxBrick.symbol, rounded_quantity, stop_loss) fxBrick.Emit_Insight() # TODO 1: Execute Rule # TODO 2: Plot Data if executed # ------------------------------------------------------------------------------------------------------------- def OnTradeClose_Short(self, data, fxBrick, closeRatio = 1): # closeRatio = 1 - close all holdings, 0.5 - close 50% of holdings, 0 - nothing to close # ------------------------------------------------------------------------------------------------------------- # avoid part closing on 1. exit (part-close) if closeRatio < 1 and not self.qcAlgo.exit_1_close: return # init price = fxBrick.data.Close # set absolute open level fxBrick.trade_abs_stop_level = price if self.qcAlgo.emit_trades: # adjust short coeff if self.holding_value > 0: self.holding_value = -1 * self.holding_value # close trade on given ratio fxBrick.trade_action("CLOSE_SHORT_" + str(closeRatio * 100) + "_PERCENT") self.trade_close(data, fxBrick, closeRatio) fxBrick.Emit_Insight() # TODO 1: Execute Rule # TODO 2: Plot Data if executed # ------------------------------------------------------------------------------------------------------------- def trade_close(self, data, fxBrick, closeRatio = 1): # closeRatio = 1 - close all holdings, 0.5 - close 50% of holdings, 0 - nothing to close # ------------------------------------------------------------------------------------------------------------- current_holding = 1 - closeRatio if current_holding < 0: current_holding = 0 if current_holding > 1: current_holding = 1 # re-balance holding coefficient self.holding_value = current_holding * self.holding_value # close via SetHoldings() self.qcAlgo.SetHoldings(fxBrick.symbol, self.holding_value) # get profit benchmarks fxBrick.get_profit_benchmarks() # ****************************************************** # * TRADE-ACTION RULES REGION TRADE RULES (BASE / END) * # ****************************************************** # ------------------------------------------------------------------------------------------------------------- def debugRunFx(self, bigData, fxStarBrick): # ------------------------------------------------------------------------------------------------------------- try: data = bigData[fxStarBrick.symbol] # validation # exit if chart is disabled if not fxStarBrick.IsChartTime(data.Time): return # go! self.debug("===================================================" ) self.debug("Run:" ) self.debug("Brick-Data: " + str(data.Time) + " : " + str(fxStarBrick.symbol)) self.debug("Current OHLC: " + str(data.Open) + " / " + str(data.High) + " / " \ + str(data.Low) + " / " + str(data.Close)) self.debug("Fluent-Anchor OHLC: " \ + str(fxStarBrick.anchor_fluent_open) + " / " \ + str(fxStarBrick.anchor_fluent_high) + " / " \ + str(fxStarBrick.anchor_fluent_low) + " / " \ + str(fxStarBrick.anchor_fluent_close)) for idx in range(fxStarBrick.scalp_max_slots): self.debug("TS-"+str(idx)+": " + str(fxStarBrick.scalpQuoteBar_RollingWindow[idx].Time)) self.debug("S-RW-"+str(idx)+": " + str(fxStarBrick.scalpQuoteBar_RollingWindow[idx])) self.debug("-----------------------------------------------" ) self.debug("Scalp Indicators:") for ind_rw_key in fxStarBrick.scalpIndicators_RollingWindows: self.debug(str("S-IND:" + ind_rw_key)) rw = fxStarBrick.scalpIndicators_RollingWindows[ind_rw_key] # show current indicator rolling window for current currency for i in range(fxStarBrick.scalp_max_slots + 1): self.debug(str(rw[i])) self.debug("-------------------------------------------------------------------------------" ) for idx in range(fxStarBrick.anchor_max_slots): self.debug("TA-"+str(idx)+": " + str(fxStarBrick.anchorQuoteBar_RollingWindow[idx].Time)) self.debug("A-RW-"+str(idx)+": " + str(fxStarBrick.anchorQuoteBar_RollingWindow[idx])) self.debug("-----------------------------------------------" ) self.debug("Anchor Indicators:") for ind_rw_key in fxStarBrick.anchorIndicators_RollingWindows.keys(): self.debug(str("A-IND:" + ind_rw_key)) rw = fxStarBrick.anchorIndicators_RollingWindows[ind_rw_key] # show current indicator rolling window for current currency for i in range(fxStarBrick.anchor_max_slots + 1): self.debug(str(rw[i])) self.debug("-------------------------------------------------------------------------------" ) except: self.debug("Error debugRunFx() with" + str(fxStarBrick.symbol)) # ------------------------------------------------------------------------------------------------------------- def debug(self, msg): # ------------------------------------------------------------------------------------------------------------- self.toolbox.show_debug(msg) # ------------------------------------------------------------------------------------------------------------- def log(self, msg): # ------------------------------------------------------------------------------------------------------------- self.toolbox.show_log(msg) # ------------------------------------------------------------------------------------------------------------- def Debug(self, msg): # ------------------------------------------------------------------------------------------------------------- self.toolbox.show_debug(msg) # ------------------------------------------------------------------------------------------------------------- def apriori_debug(self, msg): # ------------------------------------------------------------------------------------------------------------- self.toolbox.Debug(msg) # ------------------------------------------------------------------------------------------------------------- def apriori_log(self, msg): # ------------------------------------------------------------------------------------------------------------- self.toolbox.Log(msg) # ------------------------------------------------------------------------------------------------------------- def pip_round(self, price): # ------------------------------------------------------------------------------------------------------------- return self.toolbox.pip_round(price) # ********************************* # * PLOT REGION (BEGIN) * # ********************************* # ------------------------------------------------------------------------------------------------------------- def plot_scalp_chart(self, fxBrick, bar): # ------------------------------------------------------------------------------------------------------------- self.plot_price_chart(fxBrick.scalp_chart.Name, fxBrick, bar) # ------------------------------------------------------------------------------------------------------------- def plot_anchor_chart(self, fxBrick, bar): # ------------------------------------------------------------------------------------------------------------- self.plot_price_chart(fxBrick.anchor_chart.Name, fxBrick, bar) # ------------------------------------------------------------------------------------------------------------- def plot_scalp_ema_cross(self, fxBrick, value): # ------------------------------------------------------------------------------------------------------------- self.plot(fxBrick.scalp_chart.Name, fxBrick.price_chart_serial_ema_cross_point, value) # ------------------------------------------------------------------------------------------------------------- def plot_anchor_ema_cross(self, fxBrick, value): # ------------------------------------------------------------------------------------------------------------- self.plot(fxBrick.anchor_chart.Name, fxBrick.price_chart_serial_ema_cross_point, value) # ------------------------------------------------------------------------------------------------------------- def plot_price_chart(self, chart_name, fxBrick, bar): # ------------------------------------------------------------------------------------------------------------- self.plot(chart_name, fxBrick.price_chart_serial_open, bar.Open) self.plot(chart_name, fxBrick.price_chart_serial_close, bar.Close) self.plot(chart_name, fxBrick.price_chart_serial_close_consolidated, bar.Close) self.plot(chart_name, fxBrick.price_chart_serial_open_price_point, bar.Open) self.plot(chart_name, fxBrick.price_chart_serial_high_price_point, bar.High) self.plot(chart_name, fxBrick.price_chart_serial_low_price_point, bar.Low) self.plot(chart_name, fxBrick.price_chart_serial_close_price_point, bar.Close) # ------------------------------------------------------------------------------------------------------------- def plot_trigger(self, fxBrick, value, isShort): # ------------------------------------------------------------------------------------------------------------- if isShort: self.plot(fxBrick.scalp_chart.Name, fxBrick.price_chart_serial_short_trigger_point, value) else: self.plot(fxBrick.scalp_chart.Name, fxBrick.price_chart_serial_long_trigger_point, value) # ------------------------------------------------------------------------------------------------------------- def plot_entry(self, fxBrick, value, isShort, isPoint): # ------------------------------------------------------------------------------------------------------------- if isShort: if isPoint: self.plot(fxBrick.scalp_chart.Name, fxBrick.price_chart_serial_short_entry_point, value) else: self.plot(fxBrick.scalp_chart.Name, fxBrick.price_chart_serial_short_entry, value) else: if isPoint: self.plot(fxBrick.scalp_chart.Name, fxBrick.price_chart_serial_long_entry_point, value) else: self.plot(fxBrick.scalp_chart.Name, fxBrick.price_chart_serial_long_entry, value) # ------------------------------------------------------------------------------------------------------------- def plot_stop_loss(self, fxBrick, value, isShort, isPoint): # ------------------------------------------------------------------------------------------------------------- if isShort: if isPoint: self.plot(fxBrick.scalp_chart.Name, fxBrick.price_chart_serial_short_stop_loss_point, value) else: self.plot(fxBrick.scalp_chart.Name, fxBrick.price_chart_serial_short_stop_loss, value) else: if isPoint: self.plot(fxBrick.scalp_chart.Name, fxBrick.price_chart_serial_long_stop_loss_point, value) else: self.plot(fxBrick.scalp_chart.Name, fxBrick.price_chart_serial_long_stop_loss, value) # ------------------------------------------------------------------------------------------------------------- def plot_exit_1(self, fxBrick, value, isShort, isPoint): # ------------------------------------------------------------------------------------------------------------- if isShort: if isPoint: self.plot(fxBrick.scalp_chart.Name, fxBrick.price_chart_serial_short_exit_1_point, value) else: self.plot(fxBrick.scalp_chart.Name, fxBrick.price_chart_serial_short_exit_1, value) else: if isPoint: self.plot(fxBrick.scalp_chart.Name, fxBrick.price_chart_serial_long_exit_1_point, value) else: self.plot(fxBrick.scalp_chart.Name, fxBrick.price_chart_serial_long_exit_1, value) # ------------------------------------------------------------------------------------------------------------- def plot_exit_2(self, fxBrick, value, isShort, isPoint): # ------------------------------------------------------------------------------------------------------------- if isShort: if isPoint: self.plot(fxBrick.scalp_chart.Name, fxBrick.price_chart_serial_short_exit_2_point, value) else: self.plot(fxBrick.scalp_chart.Name, fxBrick.price_chart_serial_short_exit_2, value) else: if isPoint: self.plot(fxBrick.scalp_chart.Name, fxBrick.price_chart_serial_long_exit_2_point, value) else: self.plot(fxBrick.scalp_chart.Name, fxBrick.price_chart_serial_long_exit_2, value) # ------------------------------------------------------------------------------------------------------------- def plot(self, chart_name, serial_name, value): # ------------------------------------------------------------------------------------------------------------- self.qcAlgo.Plot(chart_name, serial_name, value) # ********************************* # * PLOT REGION (END) * # *********************************
# custom inpots from ForexTrendBase import ForexTrendBase from FxRedBirdBrick_South import FxRedBirdBrick_South from StrategyFxRedBird_South import StrategyFxRedBird_South # ******************************** class ForexRedBird_South(ForexTrendBase): # ******************************** # ----------------------------------------------------------- # Initializer (Cosntructor) # ------------------------------------------------------------ def Initializie(self): # ------------------------------------------------------------ # base initializer super(ForexRedBird_South, self).Initializie() # main initializer self.SetBrokerageModel(AlphaStreamsBrokerageModel()) # setup forex brokerages if self.Broker == "FXCM": self.SetBrokerageModel(BrokerageName.FxcmBrokerage) else: self.SetBrokerageModel(BrokerageName.OandaBrokerage) # ------------------ # custom selector method # ----------------------------------------------------------------------------------------------------------- def selectStrategy(self): # ----------------------------------------------------------------------------------------------------------- return StrategyFxRedBird_South(self, self.forex_galaxy, self.resolution, self.anchorResolution, self.scalp_period, self.anchor_period, self.show_debug, self.show_log, self.anchor_max_slots) # ------------------ # custom selector # ----------------------------------------------------------------------------------------------------------- def selectGalaxyStars(self): # ----------------------------------------------------------------------------------------------------------- # init strategy galaxy selected_galaxy = self.selectGalaxy(self.get_str_param("selected_galaxy")) #self.toolbox.show_log result = {} # create galaxy of fx symbol bricks for fxTickerStar in selected_galaxy: fxStarWeight = selected_galaxy[fxTickerStar] result[fxTickerStar] = FxRedBirdBrick_South(self, fxTickerStar, fxStarWeight, self.resolution, self.anchorResolution, self.scalp_period, self.anchor_period, self.show_debug, self.show_log, self.anchor_max_slots, self.scalp_max_slots) # finally return result # ----------------------------------------------------------------------------------------------------------- def OnOrderEvent(self, orderEvent): # ----------------------------------------------------------------------------------------------------------- return ''' # init filledOrderId = orderEvent.OrderId overrule_veto = False # looping all symbol bricks for fxBrickSymbol in self.forex_galaxy: if fxBrickSymbol == str(orderEvent.Symbol): fxBrick = self.forex_galaxy[fxBrickSymbol] #if fxBrick.Ignore_Cancel_Event: # if fxBrick.trade_state == fxBrick.STAND_BY: # return #else: show_action = False #not fxBrick.Ignore_Cancel_Event state_reset = False #not fxBrick.Ignore_Cancel_Event # If the ProfitTarget order was filled, close the StopLoss order if fxBrick.match_order(fxBrick.ProfitTarget, filledOrderId): if fxBrick.cancel_stop_loss(overrule_veto, show_action, state_reset): fxBrick.trade_action_filled_tp_cancel_sl() # If the StopLoss order was filled, close the ProfitTarget if fxBrick.match_order(fxBrick.StopLoss, filledOrderId): if fxBrick.cancel_take_profit(overrule_veto, show_action, state_reset): fxBrick.trade_action_filled_sl_cancel_tp() '''
from ForexSymbolBrick import ForexSymbolBrick from QuantConnect.Data import * from QuantConnect import * class FxRedBirdBrick_South(ForexSymbolBrick): def __init__(self,qcAlgo, ticker, weight, resolution, anchorResolution, scalpPeriod, anchorPeriod, showDebug = False, showLog = False, anchor_max_slots = 24, scalp_max_slots = 10): super(FxRedBirdBrick_South, self).__init__(qcAlgo, ticker, weight, resolution, anchorResolution, scalpPeriod, anchorPeriod, \ showDebug, showLog, anchor_max_slots, scalp_max_slots) # params candidates self.delta_accelerate_max_ratio = 3 #5 #3 #2.7 # 0 deactivate self.orange_risk_invert_weight = 5 self.red_risk_shift_percent = 10 self.exit2_level_min_steps_count = -1 #7 # deactivate = -1 self.RCT_pullback_trailing_stop_ratio = 0 # 0 = deactivate # trailing props self.TTG_trailing_trade_gain = 0 self.TLG_trailing_live_gain = 0 self.LLo_lowest_low_open = 0 self.LLc_lowest_low_close = 0 self.HHo_highest_high_open = 0 self.HHc_highest_high_close = 0 self.LVo_live_open = 0 self.LVc_live_close = 0 # delta props self.minor_delta = 0 self.major_delta = 0 self.delta_acceleration = 0 # semafor props self.IsLevel_Exit_1_Semafor = False self.IsLevel_Exit_2_Semafor = False self.exit2_level_steps_count = 0 # trade control props self.trade_lowest_low = 0 self.trade_highest_high = 0 self.lowest_low_last_trailng_qbars = 0 self.highest_high_last_trailng_qbars = 0 self.touch_level = 0 self.exit_1_rate = self.qcAlgo.exit_1_rate # machine states self.EXIT_1_SHORT = self.EXIT_1_SHORT_BASE self.EXIT_1_LONG = self.EXIT_1_LONG_BASE self.EXIT_2_SHORT = self.EXIT_2_SHORT_BASE self.EXIT_2_LONG = self.EXIT_2_LONG_BASE # fast-ema trigger tolerance to bar touch delta (pips) self.bar_to_fast_indicator_touch_delta_trigger_pips = self.qcAlgo.touch_trigger_pip_tolerance # slow-ema stopper toleracnce to bar touch delta (pips) self.bar_to_slow_inidcator_touch_delta_stopper_pips = self.qcAlgo.touch_trigger_pip_tolerance # * TRADE RULES/EVENTS REGION (CUSTOM / BEGIN) * def calc_trade_props(self, rolling_window_qoute_bar, lookback_steps, bar_touch_margins, trigger_pips_up, trigger_pips_down): # long trade props if self.is_long_trade: self.stop_loss_level = self.touch_level self.trade_highest_high = self.Get_Trade_Scalp_Highest_High(rolling_window_qoute_bar, lookback_steps, bar_touch_margins) self.entry_level = self.plus_pip(self.trade_highest_high, trigger_pips_up) self.trade_risk = abs(self.entry_level - self.stop_loss_level) self.trade_break_even = self.entry_level + self.trade_risk self.trade_exit = self.trade_break_even + self.trade_risk self.trade_take_profit = self.trade_exit # short trade props if self.is_short_trade: self.stop_loss_level = self.touch_level self.trade_lowest_low = self.Get_Trade_Scalp_Lowest_Low(rolling_window_qoute_bar, lookback_steps, bar_touch_margins) self.entry_level = self.plus_pip(self.trade_lowest_low, trigger_pips_down) self.trade_risk = abs(self.entry_level - self.stop_loss_level) self.trade_break_even = self.entry_level - self.trade_risk self.trade_exit = self.trade_break_even - self.trade_risk self.trade_take_profit = self.trade_exit def invert_break_even(self): # long trade props if self.is_long_trade: self.trade_break_even = self.entry_level - self.orange_risk_invert_weight * self.trade_risk # short trade props if self.is_short_trade: self.trade_break_even = self.entry_level + self.orange_risk_invert_weight * self.trade_risk def calc_on_break_even(self): # common trade props (short/long) self.stop_loss_level = self.entry_level # self.trade_break_even = 0 def calc_diff_range(self, rw_qb, d_idx, u_idx): o = 0 c = 0 for i in range(d_idx, u_idx): if self.is_long_trade: if o == 0 or o > rw_qb[i].Open: o = rw_qb[i].Open if c == 0 or c < rw_qb[i].Close: c = rw_qb[i].Close if self.is_short_trade: if o == 0 or o < rw_qb[i].Open: o = rw_qb[i].Open if c == 0 or c > rw_qb[i].Close: c = rw_qb[i].Close return o, c def calc_diff_delta(self, rw_qb): # init a_len_major = rw_qb.Size a_len_minor = int(a_len_major / 2) # go! minor_o, minor_c = self.calc_diff_range(rw_qb, 0, a_len_minor) major_o, major_c = self.calc_diff_range(rw_qb, a_len_minor, a_len_major) self.minor_delta = minor_c - minor_o self.major_delta = major_c - major_o if self.minor_delta != 0: self.delta_acceleration = abs(self.major_delta / self.minor_delta) else: self.delta_acceleration = 0 def Is_Support_Level(self, rw_qb): if self.delta_accelerate_max_ratio == 0: return False else: self.calc_diff_delta(rw_qb) return self.major_delta < 0 and self.delta_acceleration > self.delta_accelerate_max_ratio #return self.delta_acceleration > self.delta_accelerate_max_ratio def Is_Resistance_Level(self, rw_qb): if self.delta_accelerate_max_ratio == 0: return False else: self.calc_diff_delta(rw_qb) return self.major_delta > 0 and self.delta_acceleration > self.delta_accelerate_max_ratio #return self.delta_acceleration > self.delta_accelerate_max_ratio def calc_rolling_trade_props(self, rolling_window_qoute_bar, lookback_steps, bar_touch_margins, trigger_pips_up, trigger_pips_down): force_open_close_touch_margins = "open_close" # init self.oc_lowest_low_last_trailng_qbars = self.Get_Trade_Scalp_Lowest_Low(rolling_window_qoute_bar, lookback_steps, force_open_close_touch_margins) self.oc_highest_high_last_trailng_qbars = self.Get_Trade_Scalp_Highest_High(rolling_window_qoute_bar, lookback_steps, force_open_close_touch_margins) self.TTG_trailing_trade_gain = abs(self.oc_highest_high_last_trailng_qbars - self.oc_lowest_low_last_trailng_qbars) self.TLG_trailing_live_gain = self.scalp_fluent_close # LONG trailing stop loss if self.trade_state == self.EXIT_1_LONG: self.lowest_low_last_trailng_qbars = self.Get_Trade_Scalp_Lowest_Low(rolling_window_qoute_bar, lookback_steps, bar_touch_margins) self.stop_loss_level = self.plus_pip(self.lowest_low_last_trailng_qbars, trigger_pips_down) self.trade_exit = 0 # exit via stop_loss only, while in trailing_exit-mode self.trade_take_profit = self.trade_exit # SHORT trailing stop loss if self.trade_state == self.EXIT_1_SHORT: self.highest_high_last_trailng_qbars = self.Get_Trade_Scalp_Highest_High(rolling_window_qoute_bar, lookback_steps, bar_touch_margins) self.stop_loss_level = self.plus_pip(self.highest_high_last_trailng_qbars, trigger_pips_up) self.trade_exit = 0 # exit via stop_loss only, while in trailing_exit-mode self.trade_take_profit = self.trade_exit # calc lookback profit def update_hh_ll_limits(self): #init live_s_o = self.scalp_fluent_open live_s_c = self.scalp_fluent_close LLo = self.LLo_lowest_low_open LLc = self.LLc_lowest_low_close HHo = self.HHo_highest_high_open HHc = self.HHc_highest_high_close #go! self.LVo_live_open = live_s_o self.LVc_live_close = live_s_c if self.is_long_trade: if LLo == 0 or LLo > live_s_o: self.LLo_lowest_low_open = live_s_o if HHc == 0 or HHc < live_s_c: self.HHc_highest_high_close = live_s_c if self.is_short_trade: if LLc == 0 or LLc > live_s_c: self.LLc_lowest_low_close = live_s_c if HHo == 0 or HHo < live_s_o: self.HHo_highest_high_open = live_s_o def Is_Pullback_Trailing_Exit(self): # init result = False # compare # long trade props if self.is_long_trade: if self.LVc_live_close < self.LVo_live_open: self.TLG_trailing_live_gain = self.HHc_highest_high_close - self.LVc_live_close self.TTG_trailing_trade_gain = self.HHc_highest_high_close - self.LLo_lowest_low_open result = self.LLo_lowest_low_open > 0 and self.HHc_highest_high_close > 0 \ and self.LVo_live_open > self.LLo_lowest_low_open \ and abs(self.TLG_trailing_live_gain / self.TTG_trailing_trade_gain) > self.RCT_pullback_trailing_stop_ratio # short trade props if self.is_short_trade: if self.LVc_live_close > self.LVo_live_open: self.TLG_trailing_live_gain = self.LVc_live_close - self.LLc_lowest_low_close self.TTG_trailing_trade_gain = self.HHo_highest_high_open - self.LLc_lowest_low_close result = self.HHo_highest_high_open > 0 and self.LLc_lowest_low_close > 0 \ and self.LVo_live_open < self.HHo_highest_high_open \ and abs(self.TLG_trailing_live_gain / self.TTG_trailing_trade_gain) > self.RCT_pullback_trailing_stop_ratio # finally return result def Check_Trade_Rules(self, data): # base super(FxRedBirdBrick_South, self).Check_Trade_Rules(data) # init environment vars rw_ai_fast = self.anchorIndicators_RollingWindows["ema_8_anchor"] rw_ai_slow = self.anchorIndicators_RollingWindows["ema_21_anchor"] rw_si_fast = self.scalpIndicators_RollingWindows["ema_8_scalp"] rw_si_slow = self.scalpIndicators_RollingWindows["ema_21_scalp"] rw_a_qb = self.anchorQuoteBar_RollingWindow rw_s_qb = self.scalpQuoteBar_RollingWindow trailing_exit_stop_bars_count = self.qcAlgo.trailing_exit_stop_loss_bars live_s_time = self.scalp_fluent_time live_s_o = self.scalp_fluent_open live_s_h = self.scalp_fluent_high live_s_l = self.scalp_fluent_low live_s_c = self.scalp_fluent_close live_s_value = live_s_c post_s_o = rw_s_qb[0].Open post_s_h = rw_s_qb[0].High post_s_l = rw_s_qb[0].Low post_s_c = rw_s_qb[0].Close prev_s_o = rw_s_qb[1].Open prev_s_h = rw_s_qb[1].High prev_s_l = rw_s_qb[1].Low prev_s_c = rw_s_qb[1].Close live_a_time = self.anchor_fluent_time live_a_o = self.anchor_fluent_open live_a_h = self.anchor_fluent_high live_a_l = self.anchor_fluent_low live_a_c = self.anchor_fluent_close live_a_value = live_a_c live_ai_fast = self.anchor_ema_current_value(8) live_ai_slow = self.anchor_ema_current_value(21) live_si_fast = self.scalp_ema_current_value(8) live_si_mid = self.scalp_ema_current_value(13) live_si_slow = self.scalp_ema_current_value(21) s_narrow = self.is_narrow_ema_scalp s_delta_pips = self.scalp_emas_pips_delta s_delta_min_pips = self.qcAlgo.scalp_delta_min_pips a_delta = self.anchor_emas_pips_delta a_delta_min_pips = self.qcAlgo.anchor_delta_min_pips bar_touch_margins = self.qcAlgo.bar_touch_margins tolerance = self.qcAlgo.touch_trigger_pip_tolerance trigger_touch_tolerance = self.bar_to_fast_indicator_touch_delta_trigger_pips stopper_touch_tolerance = self.bar_to_slow_inidcator_touch_delta_stopper_pips trigger_pips_up = self.qcAlgo.pullback_trigger_pips_up trigger_pips_down = self.qcAlgo.pullback_trigger_pips_down exit_trailing = self.qcAlgo.exit_strategy_trailing_exit exit_break_even = self.qcAlgo.exit_strategy_break_even_exit take_profit_limit = self.qcAlgo.take_profit stop_loss_limit = self.qcAlgo.take_profit # exit_trailing startegy has bigger prioriry if exit_trailing and exit_break_even: exit_break_even = False exit_trailing = True else: if not exit_trailing and not exit_break_even: exit_trailing = True exit_break_even = False # Go! if self.check_trade_allowed: # Init trade section vars self.trade_confidence = 1 live_idx = 0 prior_idx = 1 level = live_s_value # * * # * HANDLE TRADE STATE-MACHINE * # * * if self.trade_state == self.STAND_BY: # --- handle STAND-BY (begin) self.IsLevel_TradeEnabled_Semafors[live_idx] = \ self.IsLevel_TradeEnabled(live_ai_fast, live_ai_slow, live_a_o, live_a_h, live_a_l, live_a_c, tolerance, bar_touch_margins) live_trade_enabled = self.IsLevel_TradeEnabled_Semafors[live_idx] self.Indicator_Deltas[live_idx] = abs(live_ai_fast - live_ai_slow) live_indicator_delta = self.Indicator_Deltas[live_idx] self.Direction_Semafors[live_idx] = \ self.Check_Trade_Direction(live_ai_fast, live_ai_slow, live_a_o, live_a_h, live_a_l, live_a_c, tolerance, bar_touch_margins) live_trade_direction = self.Direction_Semafors[live_idx] # check if trade is enabled if live_trade_enabled: # check anchor history rules hist_trade_enabled = True hist_trade_direction_match = True hist_ind_expanded = True hist_ind_expanded_sum = 0 hist_ind_expanded_count = 0 hist_ind_expanded_avg = 0 for ha_idx in range(1, self.anchor_max_slots + 1): # init self.Indicator_Deltas[ha_idx] = 0 qb_idx = ha_idx - 1 hist_ai_fast = self.value(rw_ai_fast[ha_idx]) hist_ai_slow = self.value(rw_ai_slow[ha_idx]) hist_indicator_delta = abs(hist_ai_fast - hist_ai_slow) # calc history enablers self.IsLevel_TradeEnabled_Semafors[ha_idx] = \ self.IsLevel_TradeEnabled(hist_ai_fast , hist_ai_slow, \ rw_a_qb[qb_idx].Open, rw_a_qb[qb_idx].High, rw_a_qb[qb_idx].Low, rw_a_qb[qb_idx].Close, \ tolerance, bar_touch_margins) # calc history direction