- edited description
Right time to increment idTrade?
Let’s suppose I want to send every minute buy limit order to exchange. When next candle is formed and order not executed, I will be cancel my previous buy limit order and send new one with new price.
I think it’s good idea to increment idTrade on Cancel event, something like that piece of code :
std::function<void()> quoteLongEnter = [&]() {
buy = new Order( OrderSide::BUY, OrderType::LIMIT, levelLongEnter, "long", idTrade );
buy->onExecuted = [&]() {
state = ProcessingState::LONG;
….
};
buy->onCancelled = [&]() {
idTrade++;
state = ProcessingState::INIT;
};
bt.SendOrder( buy );
};
But if I run this code R crash! :(
If I not increment idTrade on Cancel event, code was run smoothly, but trading log is inconsistent: only first order added to trade (see attachments).
Comments (4)
-
reporter -
reporter - edited description
-
repo owner Could you provide me with the strategy cpp code similar to QuantTools examples so I could debug it. I need the simplest version of it. R shouldn't crash anyway. I will add relevant exception to Processor.
-
reporter As I understood the crash happen when processor trying to add record in Trades table with already exist ID due to incorrect strategy code / wrong TradeID increment.
// [[Rcpp::plugins(cpp11)]] // [[Rcpp::depends(QuantTools)]] #include <Rcpp.h> #include "BackTest.h" // [[Rcpp::export]] Rcpp::List breakout_limit_orders( Rcpp::DataFrame ticks, Rcpp::List parameters, Rcpp::List options, bool fast = false ) { int smaPeriod = parameters["sma_period" ]; int timeFrame = parameters["timeframe" ]; enum class ProcessingState{ INIT, LONG, FLAT }; ProcessingState state = ProcessingState::INIT; int idTrade = 0; Sma sma( smaPeriod ); Processor bt( timeFrame ); bt.SetOptions( options ); bool isTradingHours = not bt.IsTradingHoursSet(); Order* buy; double levelLongEnter; double stopLoss = -0.05; double takeProfit = 0.1; std::function<void()> quoteLongEnter = [&]() { buy = new Order( OrderSide::BUY, OrderType::LIMIT, levelLongEnter, "long", idTrade ); buy->onExecuted = [&]() { state = ProcessingState::LONG; Order* buy_tp = new Order( OrderSide::SELL, OrderType::LIMIT, levelLongEnter+takeProfit, "long take profit", idTrade ); buy_tp->onExecuted = [&]() { state = ProcessingState::INIT; idTrade++; }; bt.SendOrder( buy_tp ); }; buy->onCancelled = [&]() { idTrade++; // the problem is here !!! comment this line and crash disappear quoteLongEnter (); }; bt.SendOrder( buy ); }; bt.onMarketOpen = [&]() { isTradingHours = true; }; bt.onMarketClose = [&]() { printf("market close!\n"); isTradingHours = false; if( state == ProcessingState::LONG ) { Order* sell = new Order( OrderSide::SELL, OrderType::MARKET, NA_REAL, "EOD", idTrade ); sell->onExecuted = [&]() { state = ProcessingState::INIT; idTrade++; }; bt.SendOrder( sell ); } }; bt.onCandle = [&]( Candle candle ) { sma.Add( candle.close ); if( not sma.IsFormed() ) return; if( not bt.CanTrade() ) return; if( not isTradingHours ) return; levelLongEnter = sma.GetValue(); switch(state) { case ProcessingState::INIT : quoteLongEnter(); state = ProcessingState::FLAT; break; case ProcessingState::FLAT : bt.CancelOrders(); // re-quote on cancel event! break; case ProcessingState::LONG : double pnl = candle.close - buy->GetExecutionPrice(); if( pnl < stopLoss ) { // create market order to close long position bt.CancelOrders(); // cancel take profit Order* sell = new Order( OrderSide::SELL, OrderType::MARKET, NA_REAL, "long stop loss", idTrade ); sell->onExecuted = [&]() { state = ProcessingState::INIT; idTrade++; }; bt.SendOrder( sell ); } break; } }; bt.Feed( ticks ); Rcpp::List summary = bt.GetSummary(); if( fast ) return summary; Rcpp::List indicators = ListBuilder().AsDataTable() .Add( bt.GetCandles() ) .Add( "sma" , sma.GetHistory() ) .Add( "pnl" , bt.GetOnCandleMarketValueHistory() ) .Add( "drawdown", bt.GetOnCandleDrawDownHistory() ); return ListBuilder() .Add( "summary" , summary ) .Add( "trades" , bt.GetTrades() ) .Add( "orders" , bt.GetOrders() ) .Add( "indicators" , indicators ) .Add( "daily_performance", bt.GetOnDayClosePerformanceHistory() ); }
- Log in to comment