joecollege Posted March 28, 2021 Report Share Posted March 28, 2021 I am new to paintbars and not fluent in C#. I want to use them to do some simple backtesting. My plan is to use the advanced editor to define the buy point using various indicators and then check the following candles to determine when the price has changed by a specified amount, say 1 %. I can't get the later candles to know the buy price. I think it must involve the "state keeping", but I don't understand what those terms do. Can someone suggest how to save a variable value so that it can be used for comparison in later candles? Thanks Quote Link to comment Share on other sites More sharing options...
Jerry Medved Posted March 28, 2021 Report Share Posted March 28, 2021 Yes, you would want to store the "buy price" in the state object, and then compare against that. Here is an example. NOTE: I am using the BuyPrice to both keep track of the buy price as well as determine. if buy has occurred. If BuyPrice is set (not zero), then it has occured, otherwise not. for the example, am using a simple calculation for determining an entry - when the price hits the day high to buy, when it pulls back from the high 1% to sell. Most of the state machinery is default added stuff. I highlighted the 2 lines that were added to it. public void MainCalculation() { // if Buy has not yet occurred, then check for a BUY condition: if (CurrentState.BuyPrice == 0 && Close >= SymbolData.High) { // BUY CurrentState.BuyPrice = Close; SetColorAndShape(Color.Green, PBShape.ArrowUp); TriggerAlert(); SetScanResult("BUY"); } else if (CurrentState.BuyPrice > 0 && Close < (SymbolData.High * 0.99)) // Check if the price dropped to 99% of the high { // SELL CurrentState.BuyPrice = 0; SetColorAndShape(Color.Green, PBShape.ArrowDn); TriggerAlert(); SetScanResult("SELL"); } } /// <summary> /// Is called at start of paintbar calculation, should be used to initialize anything needed for the paintbar /// </summary> private void PaintbarInitialize() { CurrentState.BuyPrice = 0; } /// <summary> /// Holds paintbar state - fill with variables needed to be preserved for next paintbar calc /// </summary> private struct PaintbarState { public Double BuyPrice; } /// <summary> /// Holds current PB state - use to calc PB, changes to it carry over to next PB calc /// </summary> private PaintbarState CurrentState; /// <summary> /// Holds saved PB state - internal /// </summary> private PaintbarState SavedState; /// <summary> /// Is called at start of paintbar calculation, should be used to clear the paintbar state /// </summary> private void PaintbarClearState() { CurrentState = new PaintbarState(); } /// <summary> /// Saves paintbar state (called internally). /// </summary> private void PaintbarSaveState() { SavedState = CurrentState; } /// <summary> /// Restores paintbar state (called internally). /// </summary> private void PaintbarRestoreState() { CurrentState = SavedState; } Quote Link to comment Share on other sites More sharing options...
joecollege Posted March 28, 2021 Author Report Share Posted March 28, 2021 Thanks for the quick response. I have run your code and it seems to work but I don't understand all the details. How can Close be greater than SymbolData.High? Is there a list somewhere of the various names of variables available (like SymbolData, close, etc) and to which candles they apply? Also it seems that after each SELL I could compute the gain or loss, add it to a running total and have a complete backtest. Comments? Quote Link to comment Share on other sites More sharing options...
Jerry Medved Posted March 29, 2021 Report Share Posted March 29, 2021 note that I am using >= not just >. That's just in case there are floating point number differences. the auto complete in the advanced editor shows various values available In Simple mode, we show everything available in the dropdown lists. stuff in "SymbolData" is NOT for the specific candle. It is the current data as shown in the portfolio. So SymbolData.high is the high for the current day, even if currently processing a candle 20 days back. So if you need to have the code check high for the day the candle is on, you would have to reference that as part of the "Horizontal Line" indicator Quote Link to comment Share on other sites More sharing options...
joecollege Posted April 2, 2021 Author Report Share Posted April 2, 2021 Things are progressing. I would like to require several conditions to exist before placing a paintbar such as MACDh crossing 0 and CCI >0. I have tried to use the If(Any...) command you describe in Advanced Looping to check for a crossing in an earlier bar. But when I do, I get compile errors about integers and double. Are there some declarations I need to make? Error Code: Compile Error at (38,229): Error# CS1593: Delegate 'System.Func<double,bool>' does not take 2 arguments Compile Error at (57,229): Error# CS1502: The best overloaded method match for 'MT.Charting.PaintbarBase.IndexedPropertyDouble.this[int]' has some invalid arguments Compile Error at (76,229): Error# CS1503: Argument 1: cannot convert from 'double' to 'int' Compile Error at (79,229): Error# CS1061: 'double' does not contain a definition for 'CrossesUp' and no extension method 'CrossesUp' accepting a first argument of type 'double' could be found (are you missing a using directive or an assembly reference?) Thanks for the help. Quote Link to comment Share on other sites More sharing options...
Mike Medved Posted April 2, 2021 Report Share Posted April 2, 2021 Give me the code that gives you the error Not just the errors. Quote Link to comment Share on other sites More sharing options...
joecollege Posted April 3, 2021 Author Report Share Posted April 3, 2021 Here is a similar one. Again, it didn't post. Quote Link to comment Share on other sites More sharing options...
joecollege Posted April 3, 2021 Author Report Share Posted April 3, 2021 OK - Plain text! if ((MACDHIST_Histogram >= 0.0)&&Any(0,4,(CCI_Line.CrossesUp(-100, 0)))); { SetColorAndShape(0xFF0A92FF, PBShape.ArrowDn); } Quote Link to comment Share on other sites More sharing options...
Mike Medved Posted April 3, 2021 Report Share Posted April 3, 2021 Ok first of all you should not have the finishing ; in the if line above. If you have that ;, it would just stop the if there and always execute the bracketed code. Second: gratz You found a bug in MT's C# preprocessing of the Any function. It was converting the if statement above to:if ((MACDHIST_Histogram[0] >= 0.0) && CCI_Line.Any(0, 4, (i, x) => { return (CCI_Line[ i ].CrossesUp(-100,0)); })) and it should have been if ((MACDHIST_Histogram[0] >= 0.0) && CCI_Line.Any(0, 4, (i, x) => { return (CCI_Line.CrossesUp(-100,0)); })) and third - there is more wrong with that line. It really should be: if ((MACDHIST_Histogram[0] >= 0.0) && CCI_Line.Any(0, 4, (i, x) => { return (CCI_Line.CrossesUp(-100,i)); })) but this will take some more fixin'. Doing that now. Quote Link to comment Share on other sites More sharing options...
Jerry Medved Posted April 3, 2021 Report Share Posted April 3, 2021 emailed you an update Quote Link to comment Share on other sites More sharing options...
joecollege Posted April 4, 2021 Author Report Share Posted April 4, 2021 Thanks. Got it. Seems to work. You have a great program that I have used since QuoteTracker. Thanks for being so understanding. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.