Fix status for position and SLTP
This commit is contained in:
@@ -402,6 +402,12 @@ public class TradingBotBase : ITradingBot
|
||||
internalPosition.ProfitAndLoss = brokerPosition.ProfitAndLoss;
|
||||
internalPosition.Status = PositionStatus.Filled;
|
||||
|
||||
// Update Open trade status when position is found on broker
|
||||
if (internalPosition.Open != null)
|
||||
{
|
||||
internalPosition.Open.SetStatus(TradeStatus.Filled);
|
||||
}
|
||||
|
||||
if (internalPosition.Status.Equals(PositionStatus.New))
|
||||
{
|
||||
await SetPositionStatus(internalPosition.SignalIdentifier, PositionStatus.Filled);
|
||||
@@ -493,6 +499,13 @@ public class TradingBotBase : ITradingBot
|
||||
$"✅ **Position Found on Broker**\nPosition is already open on broker\nUpdating position status to Filled");
|
||||
|
||||
UpdatePositionPnl(positionForSignal.Identifier, brokerPosition.ProfitAndLoss.Realized);
|
||||
|
||||
// Update Open trade status when position is found on broker with 2 orders
|
||||
if (internalPosition.Open != null)
|
||||
{
|
||||
internalPosition.Open.SetStatus(TradeStatus.Filled);
|
||||
}
|
||||
|
||||
await SetPositionStatus(signal.Identifier, PositionStatus.Filled);
|
||||
|
||||
// Notify platform summary about the executed trade
|
||||
@@ -568,56 +581,130 @@ public class TradingBotBase : ITradingBot
|
||||
{
|
||||
if (positionForSignal.StopLoss.Price >= lastCandle.Low)
|
||||
{
|
||||
await LogInformation(
|
||||
$"🛑 **Stop Loss Hit**\nClosing LONG position\nPrice: `${positionForSignal.StopLoss.Price}`");
|
||||
await CloseTrade(signal, positionForSignal, positionForSignal.StopLoss,
|
||||
positionForSignal.StopLoss.Price, true);
|
||||
// Use actual execution price (lastCandle.Low for SL hit)
|
||||
var executionPrice = lastCandle.Low;
|
||||
positionForSignal.StopLoss.SetPrice(executionPrice, 2);
|
||||
positionForSignal.StopLoss.SetDate(lastCandle.Date);
|
||||
positionForSignal.StopLoss.SetStatus(TradeStatus.Filled);
|
||||
|
||||
// Cancel TP trades when SL is hit
|
||||
if (positionForSignal.TakeProfit1 != null)
|
||||
{
|
||||
positionForSignal.TakeProfit1.SetStatus(TradeStatus.Cancelled);
|
||||
}
|
||||
if (positionForSignal.TakeProfit2 != null)
|
||||
{
|
||||
positionForSignal.TakeProfit2.SetStatus(TradeStatus.Cancelled);
|
||||
}
|
||||
|
||||
await LogInformation(
|
||||
$"🛑 **Stop Loss Hit**\nClosing LONG position\nPrice: `${executionPrice:F2}` (was `${positionForSignal.StopLoss.Price:F2}`)");
|
||||
await CloseTrade(signal, positionForSignal, positionForSignal.StopLoss,
|
||||
executionPrice, true);
|
||||
}
|
||||
else if (positionForSignal.TakeProfit1.Price <= lastCandle.High &&
|
||||
positionForSignal.TakeProfit1.Status != TradeStatus.Filled)
|
||||
{
|
||||
await LogInformation(
|
||||
$"🎯 **Take Profit 1 Hit**\nClosing LONG position\nPrice: `${positionForSignal.TakeProfit1.Price}`");
|
||||
await CloseTrade(signal, positionForSignal, positionForSignal.TakeProfit1,
|
||||
positionForSignal.TakeProfit1.Price, positionForSignal.TakeProfit2 == null);
|
||||
// Use actual execution price (lastCandle.High for TP hit)
|
||||
var executionPrice = lastCandle.High;
|
||||
positionForSignal.TakeProfit1.SetPrice(executionPrice, 2);
|
||||
positionForSignal.TakeProfit1.SetDate(lastCandle.Date);
|
||||
positionForSignal.TakeProfit1.SetStatus(TradeStatus.Filled);
|
||||
|
||||
// Cancel SL trade when TP is hit
|
||||
if (positionForSignal.StopLoss != null)
|
||||
{
|
||||
positionForSignal.StopLoss.SetStatus(TradeStatus.Cancelled);
|
||||
}
|
||||
|
||||
await LogInformation(
|
||||
$"🎯 **Take Profit 1 Hit**\nClosing LONG position\nPrice: `${executionPrice:F2}` (was `${positionForSignal.TakeProfit1.Price:F2}`)");
|
||||
await CloseTrade(signal, positionForSignal, positionForSignal.TakeProfit1,
|
||||
executionPrice, positionForSignal.TakeProfit2 == null);
|
||||
}
|
||||
else if (positionForSignal.TakeProfit2?.Price <= lastCandle.High)
|
||||
{
|
||||
await LogInformation(
|
||||
$"🎯 **Take Profit 2 Hit**\nClosing LONG position\nPrice: `${positionForSignal.TakeProfit2.Price}`");
|
||||
await CloseTrade(signal, positionForSignal, positionForSignal.TakeProfit2,
|
||||
positionForSignal.TakeProfit2.Price, true);
|
||||
// Use actual execution price (lastCandle.High for TP hit)
|
||||
var executionPrice = lastCandle.High;
|
||||
positionForSignal.TakeProfit2.SetPrice(executionPrice, 2);
|
||||
positionForSignal.TakeProfit2.SetDate(lastCandle.Date);
|
||||
positionForSignal.TakeProfit2.SetStatus(TradeStatus.Filled);
|
||||
|
||||
// Cancel SL trade when TP is hit
|
||||
if (positionForSignal.StopLoss != null)
|
||||
{
|
||||
positionForSignal.StopLoss.SetStatus(TradeStatus.Cancelled);
|
||||
}
|
||||
|
||||
await LogInformation(
|
||||
$"🎯 **Take Profit 2 Hit**\nClosing LONG position\nPrice: `${executionPrice:F2}` (was `${positionForSignal.TakeProfit2.Price:F2}`)");
|
||||
await CloseTrade(signal, positionForSignal, positionForSignal.TakeProfit2,
|
||||
executionPrice, true);
|
||||
}
|
||||
}
|
||||
else if (positionForSignal.OriginDirection == TradeDirection.Short)
|
||||
{
|
||||
if (positionForSignal.StopLoss.Price <= lastCandle.High)
|
||||
{
|
||||
await LogInformation(
|
||||
$"🛑 **Stop Loss Hit**\nClosing SHORT position\nPrice: `${positionForSignal.StopLoss.Price}`");
|
||||
await CloseTrade(signal, positionForSignal, positionForSignal.StopLoss,
|
||||
positionForSignal.StopLoss.Price, true);
|
||||
// Use actual execution price (lastCandle.High for SL hit on SHORT)
|
||||
var executionPrice = lastCandle.High;
|
||||
positionForSignal.StopLoss.SetPrice(executionPrice, 2);
|
||||
positionForSignal.StopLoss.SetDate(lastCandle.Date);
|
||||
positionForSignal.StopLoss.SetStatus(TradeStatus.Filled);
|
||||
|
||||
// Cancel TP trades when SL is hit
|
||||
if (positionForSignal.TakeProfit1 != null)
|
||||
{
|
||||
positionForSignal.TakeProfit1.SetStatus(TradeStatus.Cancelled);
|
||||
}
|
||||
if (positionForSignal.TakeProfit2 != null)
|
||||
{
|
||||
positionForSignal.TakeProfit2.SetStatus(TradeStatus.Cancelled);
|
||||
}
|
||||
|
||||
await LogInformation(
|
||||
$"🛑 **Stop Loss Hit**\nClosing SHORT position\nPrice: `${executionPrice:F2}` (was `${positionForSignal.StopLoss.Price:F2}`)");
|
||||
await CloseTrade(signal, positionForSignal, positionForSignal.StopLoss,
|
||||
executionPrice, true);
|
||||
}
|
||||
else if (positionForSignal.TakeProfit1.Price >= lastCandle.Low &&
|
||||
positionForSignal.TakeProfit1.Status != TradeStatus.Filled)
|
||||
{
|
||||
await LogInformation(
|
||||
$"🎯 **Take Profit 1 Hit**\nClosing SHORT position\nPrice: `${positionForSignal.TakeProfit1.Price}`");
|
||||
await CloseTrade(signal, positionForSignal, positionForSignal.TakeProfit1,
|
||||
positionForSignal.TakeProfit1.Price, positionForSignal.TakeProfit2 == null);
|
||||
// Use actual execution price (lastCandle.Low for TP hit on SHORT)
|
||||
var executionPrice = lastCandle.Low;
|
||||
positionForSignal.TakeProfit1.SetPrice(executionPrice, 2);
|
||||
positionForSignal.TakeProfit1.SetDate(lastCandle.Date);
|
||||
positionForSignal.TakeProfit1.SetStatus(TradeStatus.Filled);
|
||||
|
||||
// Cancel SL trade when TP is hit
|
||||
if (positionForSignal.StopLoss != null)
|
||||
{
|
||||
positionForSignal.StopLoss.SetStatus(TradeStatus.Cancelled);
|
||||
}
|
||||
|
||||
await LogInformation(
|
||||
$"🎯 **Take Profit 1 Hit**\nClosing SHORT position\nPrice: `${executionPrice:F2}` (was `${positionForSignal.TakeProfit1.Price:F2}`)");
|
||||
await CloseTrade(signal, positionForSignal, positionForSignal.TakeProfit1,
|
||||
executionPrice, positionForSignal.TakeProfit2 == null);
|
||||
}
|
||||
else if (positionForSignal.TakeProfit2?.Price >= lastCandle.Low)
|
||||
{
|
||||
await LogInformation(
|
||||
$"🎯 **Take Profit 2 Hit**\nClosing SHORT position\nPrice: `${positionForSignal.TakeProfit2.Price}`");
|
||||
await CloseTrade(signal, positionForSignal, positionForSignal.TakeProfit2,
|
||||
positionForSignal.TakeProfit2.Price, true);
|
||||
// Use actual execution price (lastCandle.Low for TP hit on SHORT)
|
||||
var executionPrice = lastCandle.Low;
|
||||
positionForSignal.TakeProfit2.SetPrice(executionPrice, 2);
|
||||
positionForSignal.TakeProfit2.SetDate(lastCandle.Date);
|
||||
positionForSignal.TakeProfit2.SetStatus(TradeStatus.Filled);
|
||||
|
||||
// Cancel SL trade when TP is hit
|
||||
if (positionForSignal.StopLoss != null)
|
||||
{
|
||||
positionForSignal.StopLoss.SetStatus(TradeStatus.Cancelled);
|
||||
}
|
||||
|
||||
await LogInformation(
|
||||
$"🎯 **Take Profit 2 Hit**\nClosing SHORT position\nPrice: `${executionPrice:F2}` (was `${positionForSignal.TakeProfit2.Price:F2}`)");
|
||||
await CloseTrade(signal, positionForSignal, positionForSignal.TakeProfit2,
|
||||
executionPrice, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -676,6 +763,12 @@ public class TradingBotBase : ITradingBot
|
||||
internalPosition.Status = PositionStatus.Filled;
|
||||
internalPosition.ProfitAndLoss = internalPosition.ProfitAndLoss;
|
||||
|
||||
// Update Open trade status when position is updated to Filled
|
||||
if (internalPosition.Open != null)
|
||||
{
|
||||
internalPosition.Open.SetStatus(TradeStatus.Filled);
|
||||
}
|
||||
|
||||
// Save updated position to database
|
||||
await tradingService.UpdatePositionAsync(internalPosition);
|
||||
});
|
||||
@@ -1137,26 +1230,52 @@ public class TradingBotBase : ITradingBot
|
||||
|
||||
if (wasStopLossHit)
|
||||
{
|
||||
closingPrice = position.StopLoss.Price;
|
||||
// Use actual execution price based on direction
|
||||
closingPrice = position.OriginDirection == TradeDirection.Long
|
||||
? minPriceRecent // For LONG, SL hits at the low
|
||||
: maxPriceRecent; // For SHORT, SL hits at the high
|
||||
|
||||
position.StopLoss.SetPrice(closingPrice, 2);
|
||||
position.StopLoss.SetDate(currentCandle.Date);
|
||||
position.StopLoss.SetStatus(TradeStatus.Filled);
|
||||
|
||||
// Cancel TP trades when SL is hit
|
||||
if (position.TakeProfit1 != null)
|
||||
{
|
||||
position.TakeProfit1.SetStatus(TradeStatus.Cancelled);
|
||||
}
|
||||
if (position.TakeProfit2 != null)
|
||||
{
|
||||
position.TakeProfit2.SetStatus(TradeStatus.Cancelled);
|
||||
}
|
||||
|
||||
Logger.LogInformation(
|
||||
$"🛑 **Stop Loss Execution Confirmed**\n" +
|
||||
$"Position: `{position.Identifier}`\n" +
|
||||
$"SL Price: `${position.StopLoss.Price:F2}` was hit\n" +
|
||||
$"SL Price: `${closingPrice:F2}` was hit (was `${position.StopLoss.Price:F2}`)\n" +
|
||||
$"Recent Low: `${minPriceRecent:F2}` | Recent High: `${maxPriceRecent:F2}`");
|
||||
}
|
||||
else if (wasTakeProfitHit)
|
||||
{
|
||||
closingPrice = position.TakeProfit1.Price;
|
||||
// Use actual execution price based on direction
|
||||
closingPrice = position.OriginDirection == TradeDirection.Long
|
||||
? maxPriceRecent // For LONG, TP hits at the high
|
||||
: minPriceRecent; // For SHORT, TP hits at the low
|
||||
|
||||
position.TakeProfit1.SetPrice(closingPrice, 2);
|
||||
position.TakeProfit1.SetDate(currentCandle.Date);
|
||||
position.TakeProfit1.SetStatus(TradeStatus.Filled);
|
||||
|
||||
// Cancel SL trade when TP is hit
|
||||
if (position.StopLoss != null)
|
||||
{
|
||||
position.StopLoss.SetStatus(TradeStatus.Cancelled);
|
||||
}
|
||||
|
||||
Logger.LogInformation(
|
||||
$"🎯 **Take Profit Execution Confirmed**\n" +
|
||||
$"Position: `{position.Identifier}`\n" +
|
||||
$"TP Price: `${position.TakeProfit1.Price:F2}` was hit\n" +
|
||||
$"TP Price: `${closingPrice:F2}` was hit (was `${position.TakeProfit1.Price:F2}`)\n" +
|
||||
$"Recent Low: `${minPriceRecent:F2}` | Recent High: `${maxPriceRecent:F2}`");
|
||||
}
|
||||
else
|
||||
@@ -1176,13 +1295,31 @@ public class TradingBotBase : ITradingBot
|
||||
|
||||
if (isManualCloseProfitable)
|
||||
{
|
||||
position.TakeProfit1.SetPrice(closingPrice, 2);
|
||||
position.TakeProfit1.SetDate(currentCandle.Date);
|
||||
position.TakeProfit1.SetStatus(TradeStatus.Filled);
|
||||
|
||||
// Cancel SL trade when TP is used for manual close
|
||||
if (position.StopLoss != null)
|
||||
{
|
||||
position.StopLoss.SetStatus(TradeStatus.Cancelled);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
position.StopLoss.SetPrice(closingPrice, 2);
|
||||
position.StopLoss.SetDate(currentCandle.Date);
|
||||
position.StopLoss.SetStatus(TradeStatus.Filled);
|
||||
|
||||
// Cancel TP trades when SL is used for manual close
|
||||
if (position.TakeProfit1 != null)
|
||||
{
|
||||
position.TakeProfit1.SetStatus(TradeStatus.Cancelled);
|
||||
}
|
||||
if (position.TakeProfit2 != null)
|
||||
{
|
||||
position.TakeProfit2.SetStatus(TradeStatus.Cancelled);
|
||||
}
|
||||
}
|
||||
|
||||
Logger.LogInformation(
|
||||
|
||||
Reference in New Issue
Block a user