private double GetLossRecoveryLotSize(ZoneLevels zoneLevels, double previousTurnTargetNetReturns, double spread, double commissionRate) { /* * Total Gain Potential(TPG) - Total Loss Potential(TPL) = 0 * Commission(CO) = Recovery Size(RS) * Commission Rate(CR) * Total Gain Potential(TPG) = Recovery Size(RS) * (Recovery Level(RL) - Stop Loss Level(SL)) -Commission(CO) * Total Loss Potential(TPL) = Previous Recovery Size(PRS) * ABS(Previous Entry Level(PEL) - Previous Stop Loss Level(PSL)) + Previous Turn Commission(PTC) -Prior Turns Total Return PTTR * Total Gain Potential(TPG) = Total Loss Potential(TPL) * * * TPG - TPL = 0 * CO = RS * CR * TPG = (RS * (RL - SL)) - CO * TPL = PRS * ABS(PEL - PSL) + PTC - PTTR * TPG = TPL * (RS * (RL - SL)) - (RS * CR) = PRS * ABS(PEL - PSL) + PTC - PTTR * RS((RL - SL) - CR) = PRS * ABS(PEL - PSL) + PTC - PTTR * RS = (PRS * ABS(PEL - PSL) + PTC - PTTR) / (RL - SL - CR) */ CalcHistory = $"LotSize: {LotSize}, EntryPrice: {EntryPrice}, zoneLevels.UpperTradingZone: {zoneLevels.TakeProfitLevel}, Commission: {Commission}, _profitMargin: {_profitMargin}, spread: {spread}, previousTurnTargetNetReturns: {previousTurnTargetNetReturns}, zoneLevels.UpperTradingZone: {zoneLevels.TakeProfitLevel}, commissionRate: {commissionRate}, _pipFactor: {_pipFactor}"; if (Position == MarketPosition.Long) { return((LotSize * (EntryPrice - zoneLevels.StopLossLevel) + Commission + _profitMargin + spread - previousTurnTargetNetReturns) / (zoneLevels.LossRecoveryLevel - zoneLevels.StopLossLevel - (commissionRate * _pipFactor))); } else if (Position == MarketPosition.Short) { return((LotSize * (zoneLevels.StopLossLevel - EntryPrice) + Commission + _profitMargin + spread - previousTurnTargetNetReturns) / (zoneLevels.StopLossLevel - zoneLevels.LossRecoveryLevel - (commissionRate * _pipFactor))); } else { return(0); } }
public RecoveryTurn(IActiveTurn activeTurn, RecoveryTurn previousTurn, ZoneLevels zoneLevel, MarketPosition entryPosition, MarketPosition turnPosition, double entryBidPrice, double entryAskPrice, double lotSize, IZoneRecoverySettings settings) { _settings = settings; _activeTurn = activeTurn; _activeTurn.Update(this); if (previousTurn == null) { TurnIndex = 0; } else { TurnIndex = previousTurn.TurnIndex + 1; } ZoneLevels = zoneLevel; _entryPosition = entryPosition; PreviousTurn = previousTurn; IsActive = true; Position = turnPosition; EntryPrice = (entryAskPrice + entryBidPrice) / 2; _currentPrice = EntryPrice; _commissionRate = _settings.CommissionRate; _profitMargin = _settings.ProfitMarginRate; LotSize = lotSize; _pipFactor = _settings.PipFactor; Commission = lotSize * _commissionRate * _settings.PipFactor; Spread = Math.Abs(entryAskPrice - entryBidPrice); MaxSlippageRate = _settings.Slippage; }
public Session(MarketPosition initPosition, double entryBidPrice, double entryAskPrice, double tradeZoneSize, double zoneRecoverySize, IZoneRecoverySettings settings) { _settings = settings; var midPrice = (entryBidPrice + entryAskPrice) / 2d; ZoneLevels = new ZoneLevels(initPosition, midPrice, tradeZoneSize, zoneRecoverySize); double profitMargin = tradeZoneSize * _settings.ProfitMarginRate; ActivePosition = new RecoveryTurn(this, null, ZoneLevels, initPosition, initPosition, entryBidPrice, entryAskPrice, _settings.InitLotSize, _settings); }
public (PriceActionResult, RecoveryTurn) PriceAction(double bid, double ask) { PreviousTurn?.PriceAction(bid, ask); _previousPrice = _currentPrice; _currentPrice = (bid + ask) / 2d; double spread = bid - ask; bool isTakeProfitLevelHit = false; bool isRecoveryLevelHit = false; if (Position == MarketPosition.Long) { _unrealizedNetProfit = ((_currentPrice - EntryPrice) * LotSize) - Commission - Spread; _unrealizedGrossProfit = (_currentPrice - EntryPrice) * LotSize; isTakeProfitLevelHit = IsActive && _currentPrice >= ZoneLevels.TakeProfitLevel; isRecoveryLevelHit = IsActive && _previousPrice > ZoneLevels.LossRecoveryLevel && _currentPrice <= ZoneLevels.LossRecoveryLevel; } else if (Position == MarketPosition.Short) { _unrealizedNetProfit = ((EntryPrice - _currentPrice) * LotSize) - Commission - Spread; _unrealizedGrossProfit = (EntryPrice - _currentPrice) * LotSize; isTakeProfitLevelHit = IsActive && _currentPrice <= ZoneLevels.TakeProfitLevel; isRecoveryLevelHit = IsActive && _previousPrice < ZoneLevels.LossRecoveryLevel && _currentPrice >= ZoneLevels.LossRecoveryLevel; } if (isTakeProfitLevelHit) { return(PriceActionResult.TakeProfitLevelHit, null); } else if (isRecoveryLevelHit) { if (IsMaximumSlippageHit(_currentPrice)) { return(PriceActionResult.MaxSlippageLevelHit, null); } else { var newPosition = Position.Reverse(); double previousTurnTargetNetReturns = GetTotalPreviousNetReturns(newPosition, PreviousTurn); double lotSize = GetLossRecoveryLotSize(ZoneLevels, previousTurnTargetNetReturns, spread, _commissionRate); IsActive = false; return(PriceActionResult.RecoveryLevelHit, new RecoveryTurn(_activeTurn, this, ZoneLevels.Reverse(), _entryPosition, newPosition, bid, ask, lotSize, _settings)); } } else { return(PriceActionResult.Nothing, null); } }