Support Board
Date/Time: Sat, 23 Nov 2024 20:59:53 +0000
Post From: ACSIL Custom Autotrading System assistance
[2024-08-06 11:27:15] |
User357489 - Posts: 72 |
implementing the above: #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 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_GTC; // 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; } } SCSFExport scsf_SweepGenie(SCStudyInterfaceRef sc) { if (sc.SetDefaults) { sc.GraphName = "Sweep Genie"; sc.AutoLoop = 1; sc.Input[0].Name = "Volume Threshold"; sc.Input[0].SetInt(1000); sc.Input[1].Name = "Order Quantity"; sc.Input[1].SetInt(1); sc.Input[2].Name = "Stop Loss Ticks"; sc.Input[2].SetInt(10); sc.Input[3].Name = "Take Profit Ticks"; sc.Input[3].SetInt(20); sc.Input[4].Name = "Trailing Stop Offset Ticks"; sc.Input[4].SetInt(5); return; } int volumeThreshold = sc.Input[0].GetInt(); int orderQuantity = sc.Input[1].GetInt(); int stopLossTicks = sc.Input[2].GetInt(); int takeProfitTicks = sc.Input[3].GetInt(); int trailingStopOffsetTicks = sc.Input[4].GetInt(); SCDateTime currentTime = sc.CurrentSystemDateTime; auto& tradeInfo = g_TradeInfo[sc.ChartNumber]; s_SCPositionData positionData; sc.GetTradePosition(positionData); int currentPosition = positionData.PositionQuantity; double currentPrice = sc.Close[sc.ArraySize - 1]; bool buyConditionMet = false; bool sellConditionMet = false; double bidMboOrderSum = 0; double askMboOrderSum = 0; // Check top 5 bid levels for (int level = 0; level < 5; ++level) { s_MarketDepthEntry bidDepthEntry; // Default initialization if (sc.GetBidMarketDepthEntryAtLevel(level, bidDepthEntry)) { const s_VolumeAtPriceV2* volumeAtPrice = nullptr; int priceInTicks = sc.PriceValueToTicks(bidDepthEntry.Price); if (sc.VolumeAtPriceForBars->GetVAPElementForPriceIfExists(sc.ArraySize - 1, priceInTicks, &volumeAtPrice)) { double bidPullingStacking = sc.GetBidMarketDepthStackPullValueAtPrice(bidDepthEntry.Price); if (bidPullingStacking >= volumeThreshold && volumeAtPrice->AskVolume > volumeAtPrice->BidVolume) { buyConditionMet = true; } } } } // Check top 5 ask levels for (int level = 0; level < 5; ++level) { s_MarketDepthEntry askDepthEntry; // Default initialization if (sc.GetAskMarketDepthEntryAtLevel(level, askDepthEntry)) { const s_VolumeAtPriceV2* volumeAtPrice = nullptr; int priceInTicks = sc.PriceValueToTicks(askDepthEntry.Price); if (sc.VolumeAtPriceForBars->GetVAPElementForPriceIfExists(sc.ArraySize - 1, priceInTicks, &volumeAtPrice)) { double askPullingStacking = sc.GetAskMarketDepthStackPullValueAtPrice(askDepthEntry.Price); if (askPullingStacking >= volumeThreshold && volumeAtPrice->BidVolume > volumeAtPrice->AskVolume) { sellConditionMet = true; } } } } // Final conditions: Only enter a trade if MBO conditions are also met if (buyConditionMet && bidMboOrderSum > askMboOrderSum) { PlaceBracketOrder(sc, tradeInfo, 1, orderQuantity, currentPrice, stopLossTicks, takeProfitTicks); } else if (sellConditionMet && askMboOrderSum > bidMboOrderSum) { PlaceBracketOrder(sc, tradeInfo, -1, orderQuantity, currentPrice, stopLossTicks, takeProfitTicks); } // Exit conditions and trailing stop management 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); if ((tradeInfo.positionType == 1 && (currentPrice <= stopLossPrice || currentPrice >= takeProfitPrice)) || (tradeInfo.positionType == -1 && (currentPrice >= stopLossPrice || currentPrice <= takeProfitPrice))) { sc.FlattenAndCancelAllOrders(); tradeInfo.tradeEntered = false; tradeInfo.positionType = 0; } else if (!tradeInfo.trailingStopActivated && tradeInfo.stopOrderID > 0 && ((tradeInfo.positionType == 1 && currentPrice >= trailingStopTriggerPrice) || (tradeInfo.positionType == -1 && currentPrice <= 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); sc.AddMessageToLog(message, 0); } else { SCString message; message.Format("Failed to modify stop order for trailing stop. Error: %d", modifyResult); sc.AddMessageToLog(message, 1); } } // Manage Breakeven Stop Logic if (!tradeInfo.stopMovedToBreakeven && tradeInfo.positionType != 0) { double breakevenPrice = tradeInfo.startPrice; if ((tradeInfo.positionType == 1 && currentPrice >= breakevenPrice) || (tradeInfo.positionType == -1 && currentPrice <= 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); sc.AddMessageToLog(message, 0); } else { SCString message; message.Format("Failed to modify stop order to breakeven. Error: %d", modifyResult); sc.AddMessageToLog(message, 1); } } } } // End of trade management logic return; } This returned: -- Starting remote build of Custom Studies Source files: sweepgeniedeltacheck.cpp. 64-bit -- 12:26:42 Allow time for the server to compile the files and build the DLL. Server: https://build2.sierrachart.com The remote build is complete. The build failed. sweepgeniedeltacheck.cpp: In function 'void scsf_SweepGenie(SCStudyInterfaceRef)': sweepgeniedeltacheck.cpp:101:46: error: cannot bind non-const lvalue reference of type 's_MarketDepthEntry&' to an rvalue of type 's_MarketDepthEntry' 101 | if (sc.GetBidMarketDepthEntryAtLevel(level, bidDepthEntry)) | ^~~~~ In file included from scstructures.h:104, from sierrachart.h:22, from sweepgeniedeltacheck.cpp:1: scconstants.h:1986:2: note: after user-defined conversion: 's_MarketDepthEntry::s_MarketDepthEntry(int)' 1986 | s_MarketDepthEntry(int DummyValue = 0) | ^~~~~~~~~~~~~~~~~~ sweepgeniedeltacheck.cpp:106:118: error: no matching function for call to 'c_VAPContainer::GetVAPElementForPriceIfExists(int, int&, const s_VolumeAtPriceV2**)' 106 | if (sc.VolumeAtPriceForBars->GetVAPElementForPriceIfExists(sc.ArraySize - 1, priceInTicks, &volumeAtPrice)) | ^ In file included from scstructures.h:108, from sierrachart.h:22, from sweepgeniedeltacheck.cpp:1: VAPContainer.h:630:13: note: candidate: 'bool c_VAPContainerBase<t_VolumeAtPrice>::GetVAPElementForPriceIfExists(unsigned int, int, t_VolumeAtPrice**, unsigned int&) [with t_VolumeAtPrice = s_VolumeAtPriceV2]' 630 | inline bool c_VAPContainerBase<t_VolumeAtPrice>::GetVAPElementForPriceIfExists | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ VAPContainer.h:630:13: note: candidate expects 4 arguments, 3 provided sweepgeniedeltacheck.cpp:122:46: error: cannot bind non-const lvalue reference of type 's_MarketDepthEntry&' to an rvalue of type 's_MarketDepthEntry' 122 | if (sc.GetAskMarketDepthEntryAtLevel(level, askDepthEntry)) | ^~~~~ In file included from scstructures.h:104, from sierrachart.h:22, from sweepgeniedeltacheck.cpp:1: scconstants.h:1986:2: note: after user-defined conversion: 's_MarketDepthEntry::s_MarketDepthEntry(int)' 1986 | s_MarketDepthEntry(int DummyValue = 0) | ^~~~~~~~~~~~~~~~~~ sweepgeniedeltacheck.cpp:127:118: error: no matching function for call to 'c_VAPContainer::GetVAPElementForPriceIfExists(int, int&, const s_VolumeAtPriceV2**)' 127 | if (sc.VolumeAtPriceForBars->GetVAPElementForPriceIfExists(sc.ArraySize - 1, priceInTicks, &volumeAtPrice)) | ^ In file included from scstructures.h:108, from sierrachart.h:22, from sweepgeniedeltacheck.cpp:1: VAPContainer.h:630:13: note: candidate: 'bool c_VAPContainerBase<t_VolumeAtPrice>::GetVAPElementForPriceIfExists(unsigned int, int, t_VolumeAtPrice**, unsigned int&) [with t_VolumeAtPrice = s_VolumeAtPriceV2]' 630 | inline bool c_VAPContainerBase<t_VolumeAtPrice>::GetVAPElementForPriceIfExists | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ VAPContainer.h:630:13: note: candidate expects 4 arguments, 3 provided -- End of Build -- 12:26:46 |