Support Board
Date/Time: Sun, 08 Sep 2024 00:11:19 +0000
[Programming Help] - Trading NQ, ES and YM from one single chart in a single account - Programming help needed
View Count: 192
[2024-06-13 02:51:33] |
User61168 - Posts: 381 |
Hi, I have a single chart with NQ on main chart along with ES and YM added via Add Symbol study. Chart type works beautifully for all 3 symbols in market play. I have 6 buy and sell entry signal alert conditions across the 3 symbols. I do not have any configuration dependency via my trade ticket window. Default trade quantity is always set to 1 and algo does the % risk based position sizing via scalein/out. Automated trading is via simple alerts only. For all trading signals, only one symbol is considered master while the other two are 'slaves'. Master could be either one of the 3 symbols. Is there a creative way for me to "selectively" enter trades on ES and YM without using chart overlays? I also cannot run 3 versions of the same chart in parallel against the same trading account as it messes up my risk/money management logic. Is it possible for someone with ASCIL knowledge to alter the C++ code for "trading system based on alert condition" study to allow passing of symbol and qty as custom inputs for trade execution? Date Time Of Last Edit: 2024-06-13 02:53:27
|
[2024-06-19 02:05:24] |
ForgivingComputers.com - Posts: 928 |
I don't think there is a way to change the trading symbol of a chart using ACSIL, other than opening a new chart with the desired parameters. Order quantity is no issue. I am curious, perhaps there is a way to have multiple charts that doesn't mess up other logic. I would be happy to look at what you need and give you a quote. brad (at) forgivingcomputers (dot) com |
[2024-07-26 11:29:59] |
User357489 - Posts: 67 |
Hi there, looking to do something similar, did you manage to resolve your issue? i have a crude chart (being the main price graph) and 2 additional symbols (es and eurofx). Just wanted something "simple" in my mind, that when commodities cross equites/ currencies etc and the permutations thereof, then enter 2 trades, opposing eg +1 crude -1 es if crude crosses es from below etc. With that being said im not sure if it can be done, as they use independent scaling. I have a skeleton code of sorts, compiles but doesn't output result and im stuck! any help, tips, pointers much appreciated, welcome to the code for your own use. #include "sierrachart.h"
#include <unordered_map> #include <chrono> SCDLLName("Cross Trading System with Brackets and Crossover Markers") 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; // To track if stop loss has been moved to breakeven int stopOrderID; // To store the stop order ID int tradeSystemID; // Unique ID for the trading system const char* symbol; // Symbol for the trade }; std::unordered_map<int, TradeInfo> g_TradeInfo; void PlaceBracketOrder(SCStudyInterfaceRef& sc, TradeInfo& tradeInfo, int positionType, int orderQuantity, double price, int tradeSystemID, double tickSize, const char* symbol) { s_SCNewOrder order; order.OrderType = SCT_ORDERTYPE_MARKET; order.OrderQuantity = orderQuantity; order.TimeInForce = SCT_TIF_GTC; // Define the attached orders order.Target1Offset = 50 * tickSize; // 50 ticks profit target order.Stop1Offset = -10 * tickSize; // 10 ticks stop loss // 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; // Initialize to false when trade is entered tradeInfo.tradeSystemID = tradeSystemID; // Store the trade system ID tradeInfo.symbol = symbol; // Store the symbol for logging // Store the stop order ID tradeInfo.stopOrderID = order.Stop1InternalOrderID; // Add a marker on the chart at the entry point s_UseTool tool; tool.Clear(); tool.ChartNumber = sc.ChartNumber; tool.DrawingType = DRAWING_MARKER; tool.BeginIndex = sc.Index; tool.BeginValue = price; tool.AddMethod = UTAM_ADD_OR_ADJUST; tool.MarkerType = (positionType == 1) ? MARKER_ARROWUP : MARKER_ARROWDOWN; tool.MarkerSize = 6; tool.Color = (positionType == 1) ? RGB(0, 255, 0) : RGB(255, 0, 0); // Green for Buy, Red for Sell sc.UseTool(tool); // Log the trade entry SCString message; message.Format("Trade entered: %s %s at price %.2f", (positionType == 1) ? "Buy" : "Sell", symbol, price); sc.AddMessageToLog(message, 0); } } void AddCrossoverMarker(SCStudyInterfaceRef& sc, int index, double price, const char* symbol1, const char* symbol2) { s_UseTool tool; tool.Clear(); tool.ChartNumber = sc.ChartNumber; tool.DrawingType = DRAWING_MARKER; tool.BeginIndex = index; tool.BeginValue = price; tool.AddMethod = UTAM_ADD_OR_ADJUST; tool.MarkerType = MARKER_X; tool.MarkerSize = 6; tool.Color = RGB(255, 255, 255); // White color for crossover marker tool.Text.Format("Crossover %s/%s", symbol1, symbol2); sc.UseTool(tool); } SCSFExport scsf_CrossoverAutoTrading(SCStudyInterfaceRef sc) { if (sc.SetDefaults) { sc.GraphName = "Cross Trading System with Brackets and Crossover Markers"; sc.GraphRegion = 0; sc.AutoLoop = 1; sc.Input[0].Name = "Order Quantity"; sc.Input[0].SetInt(1); sc.Input[1].Name = "Trade System ID"; sc.Input[1].SetInt(1); // Unique ID for this trading system sc.Input[2].Name = "Start Time (HHMM)"; sc.Input[2].SetInt(930); // Default start time is 9:30 AM sc.Input[3].Name = "End Time (HHMM)"; sc.Input[3].SetInt(1600); // Default end time is 4:00 PM return; } int orderQuantity = sc.Input[0].GetInt(); int tradeSystemID = sc.Input[1].GetInt(); int startTime = sc.Input[2].GetInt(); int endTime = sc.Input[3].GetInt(); SCDateTime currentDateTime = sc.BaseDateTimeIn[sc.Index]; int currentTime = currentDateTime.GetTimeAsSCDateTime().GetTimeInSeconds() / 100; // Get time as HHMM // Check if current time is within the specified trading window if (currentTime < startTime || currentTime > endTime) { return; } // Define tick sizes for different symbols std::unordered_map<int, double> tickSizes; tickSizes[2] = 0.25; // SP tick size tickSizes[3] = 0.00005; // Euro tick size // Variables to store the price data from the studies SCFloatArray spData; SCFloatArray euroData; // Get the data from the specified studies sc.GetStudyArrayUsingID(2, 4, spData); sc.GetStudyArrayUsingID(3, 4, euroData); // Ensure the data arrays are valid if (spData.GetArraySize() == 0 || euroData.GetArraySize() == 0) { return; } // Variables to store the price data float oilPrice = sc.BaseDataIn[SC_LAST][sc.Index]; // Crude oil last price float spPrice = spData[sc.Index]; float euroPrice = euroData[sc.Index]; // Check for crossover conditions auto CheckCrossover = [&](float price1, float prevPrice1, float price2, float prevPrice2) { return (price1 > price2 && prevPrice1 <= prevPrice2) || (price1 < price2 && prevPrice1 >= prevPrice2); }; // Function to execute trades with bracket orders auto ExecuteBracketTrade = [&](float current1, float current2, int positionType1, int positionType2, const char* symbol1, const char* symbol2, double tickSize1, double tickSize2) { double price1 = current1; double price2 = current2; auto& tradeInfo1 = g_TradeInfo[sc.ChartNumber * 10 + positionType1]; auto& tradeInfo2 = g_TradeInfo[sc.ChartNumber * 10 + positionType2]; if (CheckCrossover(current1, sc.BaseDataIn[SC_LAST][sc.Index - 1], current2, sc.BaseDataIn[SC_LAST][sc.Index - 1])) { // Buy the first asset with a bracket order PlaceBracketOrder(sc, tradeInfo1, 1, orderQuantity, price1, tradeSystemID, tickSize1, symbol1); // Sell the second asset with a bracket order PlaceBracketOrder(sc, tradeInfo2, -1, orderQuantity, price2, tradeSystemID, tickSize2, symbol2); SCString message; message.Format("+1 %s, -1 %s", symbol1, symbol2); sc.AddMessageToLog(message, 0); // Add crossover marker AddCrossoverMarker(sc, sc.Index, price1, symbol1, symbol2); } else if (CheckCrossover(current2, sc.BaseDataIn[SC_LAST][sc.Index - 1], current1, sc.BaseDataIn[SC_LAST][sc.Index - 1])) { // Sell the first asset with a bracket order PlaceBracketOrder(sc, tradeInfo1, -1, orderQuantity, price1, tradeSystemID, tickSize1, symbol1); // Buy the second asset with a bracket order PlaceBracketOrder(sc, tradeInfo2, 1, orderQuantity, price2, tradeSystemID, tickSize2, symbol2); SCString message; message.Format("-1 %s, +1 %s", symbol1, symbol2); sc.AddMessageToLog(message, 0); // Add crossover marker AddCrossoverMarker(sc, sc.Index, price2, symbol1, symbol2); } }; ExecuteBracketTrade(oilPrice, spPrice, 1, -1, "CL", "ES", 0.01, 0.25); // Oil vs SP ExecuteBracketTrade(oilPrice, euroPrice, 1, -1, "CL", "EUR", 0.01, 0.00005); // Oil vs Euro ExecuteBracketTrade(spPrice, euroPrice, 1, -1, "ES", "EUR", 0.25, 0.00005); // SP vs Euro } |
![]() |
To post a message in this thread, you need to log in with your Sierra Chart account: