Support Board
Date/Time: Sat, 23 Nov 2024 17:56:54 +0000
Post From: ACSIL Custom Autotrading System assistance
[2024-08-12 08:06:12] |
User357489 - Posts: 72 |
Good morning, no rest for the wicked! Since breaking it down into smaller chunks so to speak, i have got 2 "entry" condition studies working as i wanted them to. So- i tried as best i could to take the logic from each one, and use them as entry conditions in the auto trading system; The build succeeded, however; its doing the same thing as before regarding trade mgt. PFA screenshots; 1 is the Trade DOM; so what i see is "FLAT" and the PNL is highlighted green, which it shouldnt if flat for a start, and the D:pnl box below, updates sporadically without seemingly opening a trade; ie i cant see the attached order fills on chart (the chart settings are correct) Here's the iteration of the auto trade, having taken the "highlighting" logic from the two other working code (attached as txt files for convenience) #include "sierrachart.h"
#include <unordered_map> #include <chrono> SCDLLName("Sweep Genie") struct TradeInfo { std::chrono::time_point<std::chrono::steady_clock> startTime; double startPrice; bool tradeEntered; int positionType; // 1 for buy, -1 for sell bool stopMovedToBreakeven; bool trailingStopActivated; int stopOrderID; }; std::unordered_map<int, TradeInfo> g_TradeInfo; void LogDebugMessage(SCStudyInterfaceRef& sc, const SCString& message) { sc.AddMessageToLog(message, 0); } void LogErrorMessage(SCStudyInterfaceRef& sc, const SCString& message) { sc.AddMessageToLog(message, 1); } void PlaceBracketOrder(SCStudyInterfaceRef& sc, TradeInfo& tradeInfo, int positionType, int orderQuantity, double price, int stopLossTicks, int takeProfitTicks) { s_SCNewOrder order; order.OrderType = SCT_ORDERTYPE_MARKET; order.OrderQuantity = orderQuantity; order.TimeInForce = SCT_TIF_DAY; // Define the attached orders order.Target1Offset = takeProfitTicks * sc.TickSize; order.Stop1Offset = stopLossTicks * sc.TickSize; // Set attached order types order.AttachedOrderTarget1Type = SCT_ORDERTYPE_LIMIT; order.AttachedOrderStop1Type = SCT_ORDERTYPE_STOP; int result = (positionType == 1) ? sc.BuyEntry(order) : sc.SellEntry(order); if (result > 0) { tradeInfo.startTime = std::chrono::steady_clock::now(); tradeInfo.startPrice = price; tradeInfo.tradeEntered = true; tradeInfo.positionType = positionType; tradeInfo.stopMovedToBreakeven = false; tradeInfo.trailingStopActivated = false; tradeInfo.stopOrderID = order.Stop1InternalOrderID; SCString message; message.Format("Trade entered: PositionType=%d, Price=%f", positionType, price); LogDebugMessage(sc, message); } else { SCString message; message.Format("Failed to enter trade: PositionType=%d, Error=%d", positionType, result); LogErrorMessage(sc, message); } } bool CheckFlashGenieHighlight(SCStudyInterfaceRef& sc, bool isBid) { int numLevels = sc.Input[1].GetInt(); double threshold = sc.Input[0].GetInt(); s_MarketDepthEntry depthEntry; for (int level = 0; level < numLevels; ++level) { if (isBid) { if (sc.GetBidMarketDepthEntryAtLevel(depthEntry, level)) { double pullingStackingBid = sc.GetBidMarketDepthStackPullValueAtPrice(depthEntry.Price); if (pullingStackingBid >= threshold) { LogDebugMessage(sc, "Flash Genie bid highlight condition met."); return true; } } } else { if (sc.GetAskMarketDepthEntryAtLevel(depthEntry, level)) { double pullingStackingAsk = sc.GetAskMarketDepthStackPullValueAtPrice(depthEntry.Price); if (pullingStackingAsk >= threshold) { LogDebugMessage(sc, "Flash Genie ask highlight condition met."); return true; } } } } return false; } bool CheckDeltaGenieHighlight(SCStudyInterfaceRef& sc, bool isBid) { int volumeProfileStudyID = sc.Input[0].GetInt(); int numLevelsToCheck = sc.Input[3].GetInt(); s_MarketDepthEntry depthEntry; s_VolumeAtPriceV2 volumeAtPriceData; for (int level = 0; level < numLevelsToCheck; ++level) { if (isBid) { if (sc.GetBidMarketDepthEntryAtLevel(depthEntry, level)) { for (int priceIndex = 0; priceIndex < sc.GetNumPriceLevelsForStudyProfile(volumeProfileStudyID, 0); ++priceIndex) { if (sc.GetVolumeAtPriceDataForStudyProfile(volumeProfileStudyID, 0, priceIndex, volumeAtPriceData)) { double vbpPrice = volumeAtPriceData.PriceInTicks * sc.TickSize; if (fabs(vbpPrice - depthEntry.Price) < sc.TickSize / 2) { if (volumeAtPriceData.AskVolume < volumeAtPriceData.BidVolume) { LogDebugMessage(sc, "Delta Genie bid highlight condition met."); return true; } } } } } } else { if (sc.GetAskMarketDepthEntryAtLevel(depthEntry, level)) { for (int priceIndex = 0; priceIndex < sc.GetNumPriceLevelsForStudyProfile(volumeProfileStudyID, 0); ++priceIndex) { if (sc.GetVolumeAtPriceDataForStudyProfile(volumeProfileStudyID, 0, priceIndex, volumeAtPriceData)) { double vbpPrice = volumeAtPriceData.PriceInTicks * sc.TickSize; if (fabs(vbpPrice - depthEntry.Price) < sc.TickSize / 2) { if (volumeAtPriceData.AskVolume > volumeAtPriceData.BidVolume) { LogDebugMessage(sc, "Delta Genie ask highlight condition met."); return true; } } } } } } } return false; } SCSFExport scsf_SweepGenie(SCStudyInterfaceRef sc) { if (sc.SetDefaults) { sc.GraphName = "Sweep Genie"; sc.GraphRegion = 0; sc.AutoLoop = 0; // Manual loop enabled // User inputs sc.Input[0].Name = "Use Start/Stop Time"; sc.Input[0].SetYesNo(0); // Default to No sc.Input[1].Name = "Start Time (HH:MM:SS)"; sc.Input[1].SetTime(HMS_TIME(9, 30, 0)); // Default start time sc.Input[2].Name = "Stop Time (HH:MM:SS)"; sc.Input[2].SetTime(HMS_TIME(16, 0, 0)); // Default stop time sc.Input[3].Name = "Volume Profile Study ID"; sc.Input[3].SetInt(7); // Set this to the actual study ID of the Volume Profile sc.Input[4].Name = "Order Quantity"; sc.Input[4].SetInt(1); sc.Input[5].Name = "Stop Loss Ticks"; sc.Input[5].SetInt(10); sc.Input[6].Name = "Take Profit Ticks"; sc.Input[6].SetInt(20); sc.Input[7].Name = "Trailing Stop Offset Ticks"; sc.Input[7].SetInt(5); sc.Input[8].Name = "Trade Type"; sc.Input[8].SetCustomInputStrings("Long;Short;Long & Short"); sc.Input[8].SetCustomInputIndex(2); // Default to Long & Short sc.Input[9].Name = "Maximum Positions Allowed"; sc.Input[9].SetInt(1); // Default to 1 position return; } bool useStartStopTime = sc.Input[0].GetYesNo(); SCDateTime startTime = sc.Input[1].GetTime(); SCDateTime stopTime = sc.Input[2].GetTime(); int volumeProfileStudyID = sc.Input[3].GetInt(); int orderQuantity = sc.Input[4].GetInt(); int stopLossTicks = sc.Input[5].GetInt(); int takeProfitTicks = sc.Input[6].GetInt(); int trailingStopOffsetTicks = sc.Input[7].GetInt(); int tradeType = sc.Input[8].GetIndex(); int maxPositionsAllowed = sc.Input[9].GetInt(); SCDateTime currentTime = sc.CurrentSystemDateTime; // Check if current time is within trading hours if (useStartStopTime && (currentTime < startTime || currentTime > stopTime)) { LogDebugMessage(sc, "Outside of trading hours. No trades will be executed."); return; } // Get current position size s_SCPositionData positionData; sc.GetTradePosition(positionData); int currentPosition = positionData.PositionQuantity; // Access the trade information auto& tradeInfo = g_TradeInfo[sc.ChartNumber]; bool buyConditionMet = false; bool sellConditionMet = false; double entryPrice = sc.Close[sc.ArraySize - 1]; // Using the current price for entry // Calculate the sum of bid and ask market depth quantities and pulling/stacking values double bidSum = 0.0; double askSum = 0.0; double pullingStackingBidSum = 0.0; double pullingStackingAskSum = 0.0; s_MarketDepthEntry depthEntry; for (int level = 0; level < sc.GetBidMarketDepthNumberOfLevels(); ++level) { if (sc.GetBidMarketDepthEntryAtLevel(depthEntry, level)) { bidSum += depthEntry.Quantity; pullingStackingBidSum += sc.GetBidMarketDepthStackPullValueAtPrice(depthEntry.Price); } } for (int level = 0; level < sc.GetAskMarketDepthNumberOfLevels(); ++level) { if (sc.GetAskMarketDepthEntryAtLevel(depthEntry, level)) { askSum += depthEntry.Quantity; pullingStackingAskSum += sc.GetAskMarketDepthStackPullValueAtPrice(depthEntry.Price); } } double totalDepthSum = bidSum + askSum; double bidSumPercentage = (totalDepthSum > 0) ? (bidSum / totalDepthSum) * 100 : 0; double askSumPercentage = (totalDepthSum > 0) ? (askSum / totalDepthSum) * 100 : 0; double bidPullStackPercentage = (pullingStackingBidSum / (pullingStackingBidSum + pullingStackingAskSum)) * 100; double askPullStackPercentage = (pullingStackingAskSum / (pullingStackingBidSum + pullingStackingAskSum)) * 100; // Buy Entry Conditions if (bidSumPercentage > askSumPercentage && // Bid sum percentage > ask sum percentage bidPullStackPercentage > askPullStackPercentage && // Bid pulling/stacking sum percentage > ask pulling/stacking sum percentage currentPosition < maxPositionsAllowed && // Current position below max positions allowed CheckFlashGenieHighlight(sc, true) && // Flash Genie bid highlight condition met CheckDeltaGenieHighlight(sc, true) && // Delta Genie bid highlight condition met tradeType != 1) // Long or Long & Short allowed { buyConditionMet = true; } // Sell Entry Conditions else if (askSumPercentage > bidSumPercentage && // Ask sum percentage > bid sum percentage askPullStackPercentage > bidPullStackPercentage && // Ask pulling/stacking sum percentage > bid pulling/stacking sum percentage currentPosition > -maxPositionsAllowed && // Current position below max positions allowed CheckFlashGenieHighlight(sc, false) && // Flash Genie ask highlight condition met CheckDeltaGenieHighlight(sc, false) && // Delta Genie ask highlight condition met tradeType != 0) // Short or Long & Short allowed { sellConditionMet = true; } // Execute Buy or Sell based on conditions if (buyConditionMet && !tradeInfo.tradeEntered) { PlaceBracketOrder(sc, tradeInfo, 1, orderQuantity, entryPrice, stopLossTicks, takeProfitTicks); } else if (sellConditionMet && !tradeInfo.tradeEntered) { PlaceBracketOrder(sc, tradeInfo, -1, orderQuantity, entryPrice, stopLossTicks, takeProfitTicks); } // Rest of the trade management logic if (tradeInfo.tradeEntered) { double stopLossPrice = tradeInfo.startPrice - (tradeInfo.positionType * stopLossTicks * sc.TickSize); double takeProfitPrice = tradeInfo.startPrice + (tradeInfo.positionType * takeProfitTicks * sc.TickSize); double trailingStopTriggerPrice = tradeInfo.startPrice + (tradeInfo.positionType * takeProfitTicks * 0.7 * sc.TickSize); // Check for stop loss or take profit condition if ((tradeInfo.positionType == 1 && (sc.Close[sc.ArraySize - 1] <= stopLossPrice || sc.Close[sc.ArraySize - 1] >= takeProfitPrice)) || (tradeInfo.positionType == -1 && (sc.Close[sc.ArraySize - 1] >= stopLossPrice || sc.Close[sc.ArraySize - 1] <= takeProfitPrice))) { sc.FlattenAndCancelAllOrders(); tradeInfo.tradeEntered = false; tradeInfo.positionType = 0; SCString message; message.Format("Trade exited: PositionType=%d, Price=%f", tradeInfo.positionType, sc.Close[sc.ArraySize - 1]); LogDebugMessage(sc, message); } else if (!tradeInfo.trailingStopActivated && tradeInfo.stopOrderID > 0 && ((tradeInfo.positionType == 1 && sc.Close[sc.ArraySize - 1] >= trailingStopTriggerPrice) || (tradeInfo.positionType == -1 && sc.Close[sc.ArraySize - 1] <= trailingStopTriggerPrice))) { tradeInfo.trailingStopActivated = true; s_SCNewOrder modifyOrder; modifyOrder.InternalOrderID = tradeInfo.stopOrderID; modifyOrder.Price1 = tradeInfo.startPrice + (tradeInfo.positionType * trailingStopOffsetTicks * sc.TickSize); int modifyResult = sc.ModifyOrder(modifyOrder); if (modifyResult == 1) { SCString message; message.Format("Trailing stop activated at price: %f", modifyOrder.Price1); LogDebugMessage(sc, message); } else { SCString message; message.Format("Failed to modify stop order for trailing stop. Error: %d", modifyResult); LogErrorMessage(sc, message); } } // Manage Breakeven Stop Logic if (!tradeInfo.stopMovedToBreakeven && tradeInfo.positionType != 0) { double breakevenPrice = tradeInfo.startPrice; if ((tradeInfo.positionType == 1 && sc.Close[sc.ArraySize - 1] >= breakevenPrice) || (tradeInfo.positionType == -1 && sc.Close[sc.ArraySize - 1] <= breakevenPrice)) { s_SCNewOrder modifyOrder; modifyOrder.InternalOrderID = tradeInfo.stopOrderID; modifyOrder.Price1 = breakevenPrice; int modifyResult = sc.ModifyOrder(modifyOrder); if (modifyResult == 1) { tradeInfo.stopMovedToBreakeven = true; SCString message; message.Format("Stop moved to breakeven at price: %f", modifyOrder.Price1); LogDebugMessage(sc, message); } else { SCString message; message.Format("Failed to modify stop order to breakeven. Error: %d", modifyResult); LogErrorMessage(sc, message); } } } // Additional Exit Logic: Any other conditions for exiting the trade can be added here } // End of trade management logic return; } its almost like it is on "auto DRAIN" mode haha, i added the condition of sumbidmarketdepth/sumask marketdepth comparisons to try bolster and make entry logic a bit more robust, but unsure as to why its buggering up, because its like it isnt giving the trade a chance , i wanted to add sum bid mbo >/<sumask mbo or something to that effect (as in a sum of all bid/ask mbo queues over X levels), again to try make the system differentiatie between a buy and a sell without it consistently drawing down while appearing FLAT, almost like daylight robbery. Date Time Of Last Edit: 2024-08-12 11:35:42
|
flashgeniebymrb.txt - Attached On 2024-08-12 08:04:42 UTC - Size: 3.17 KB - 122 views deltageniebymrb.txt - Attached On 2024-08-12 08:04:55 UTC - Size: 5.19 KB - 118 views |