Machine Learning in ProOrder ProRealTime
Forums › ProRealTime English forum › ProOrder support › Machine Learning in ProOrder ProRealTime
- This topic has 454 replies, 32 voices, and was last updated 2 years ago by Khaled.
Tagged: machine learning
-
-
04/28/2020 at 1:29 PM #128620
1. Moreover generally the parameter where the best we obtain with a backtest and changing the valuex will result in choosing a worst combinaison of values
2. And to conclude determining that a valuex of 12 the 4 april doesn’t mean it will be the best value for the 12 april for exampleSurely you have sort of answered your own question 1 with the bold text in question 2?
It may be that the System you are experimenting with has variable values (arrived at via normal optimisation / WF etc) that are at their best ever value?
If the Heuristics are used in a System where a variable optimum value can changes every day or so (like the Renkos we have been using on this Topic) then the Heurisitic on the fly optimisation can improve results.
04/28/2020 at 1:32 PM #128621Also important to note that each discovery session is determined by ‘MaxIncrement’ (number of increments to try). After this the strategy then tests the newly discovered best values for a number of trades as defined by ‘Reps’. It then compares the results to the previous discovery session and overall best values to see whether progress was made.
Unfortunately determining true market cycles is extremely challenging and for now the heuristics (i.e. discovery through ‘trial and error’) is my best shot at dynamic optimization.
1 user thanked author for this post.
04/28/2020 at 1:54 PM #128628Also important to note that each discovery session is determined by ‘MaxIncrement’ (number of increments to try). After this the strategy then tests the newly discovered best values for a number of trades as defined by ‘Reps’. It then compares the results to the previous discovery session and overall best values to see whether progress was made.
Unfortunately determining true market cycles is extremely challenging and for now the heuristics (i.e. discovery through ‘trial and error’) is my best shot at dynamic optimization.
the strategy then tests the newly discovered best values for a number of trades as defined by ‘Reps
It’s like a forward test in live, right ? But with the risk it getting worst with losing trades with the new values ?
04/28/2020 at 2:44 PM #128638@juanj a while back we discussed about the importance of MFA/MAE ratio.
If you had a stoploss of 500points and a target of 50 points, takes the current way of calculation parameters into account that if the trade goes -450 before it reached 50 points it wasn’t very good entry or does it see as a positive trade and parameters which could be used again?
@Bard
“Unfortunately SET STOP PTRAILING does not use tick by tick data and so gives false results.” That’s a bunch of time wasted. Knew there was something off but not exactly what.
Atleast v4 ts had this covered. I thought the order would be rejected, but as it stands it was accepted today and having good results.
1 user thanked author for this post.
04/28/2020 at 2:53 PM #128641An other idea came to mind.
instead of use ML for parameters, what about using the optimistation results and group the first 10 rows with parameters.
Then ML can take out of those 10 row which set of parameters will be the best. Especially on a short timeframe (1s-10s), a few days later again optimisation can be made and the best set of parameters added to the first group, so you buildup data for ML which covers more market scenarios.
Baloney or interesting?
1 user thanked author for this post.
04/28/2020 at 2:55 PM #128643To continue, because it’s an intersting topic (Thanks @juanj and all contributors), I made a test
I use a very simple code
12345678910111213141516171819202122232425262728// Définition des paramètres du codeDEFPARAM CumulateOrders = False // Cumul des positions désactivé// Conditions pour ouvrir une position acheteuseindicator1 = ExponentialAverage[a](close)indicator2 = ExponentialAverage[b](close)c1 = (indicator1 CROSSES OVER indicator2)indicator3 = WilderAverage[c](close)c2 = (close > indicator3)IF c1 AND c2 THENBUY 1 SHARES AT MARKETENDIF// Conditions pour ouvrir une position en vente à découvertindicator4 = ExponentialAverage[a](close)indicator5 = ExponentialAverage[b](close)c3 = (indicator4 CROSSES UNDER indicator5)indicator6 = WilderAverage[c](close)c4 = (close < indicator6)IF c3 AND c4 THENSELLSHORT 1 SHARES AT MARKETENDIF// Stops et objectifsSET TARGET pPROFIT dSET STOP pLOSS 2*dOn EUR/USD 1 minute. I do a backtest and obtain the “best” value who are a=30 b=60 c=30 d=4
I put these values in the Learning machine in Starting Value as you can see below with min/max as the values aroud these values on the backtest
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323defparam cumulateorders = false//////////////////////////////////////////////////////////////StartingValue = 30ResetPeriod = 3 //Specify no of months after which to reset optimizationIncrement = 1MaxIncrement = 20 //Limit of no of increments either up or downReps = 3 //Number of trades to use for analysisMinValue = 10 //Minimum allowed valueMaxValue = 100 //Maximum allowed value//////////////////////////////////////////////////////////////StartingValue2 = 60ResetPeriod2 = 3 //Specify no of months after which to reset optimizationIncrement2 = 1MaxIncrement2 = 20 //Limit of no of increments either up or downReps2 = 3 //Number of trades to use for analysisMinValue2 = 20 //Minimum allowed valueMaxValue2 = 100 //Maximum allowed value////////////////////////////////////////////////////////////////period1=7//period2=14HeuristicsCycleLimit = 2once HeuristicsCycle = 0once HeuristicsAlgo1 = 1once HeuristicsAlgo2 = 0If HeuristicsCycle >= HeuristicsCycleLimit ThenIf HeuristicsAlgo1 = 1 ThenHeuristicsAlgo2 = 1HeuristicsAlgo1 = 0ElsIf HeuristicsAlgo2 = 1 ThenHeuristicsAlgo1 = 1HeuristicsAlgo2 = 0EndIfHeuristicsCycle = 0EndIf////If HeuristicsAlgo1 = 1 Then//Heuristics Algorithm 1 StartIf (onmarket[1] = 1 and onmarket = 0) or (longonmarket[1] = 1 and longonmarket and countoflongshares < countoflongshares[1]) or (longonmarket[1] = 1 and longonmarket and countoflongshares > countoflongshares[1]) or (shortonmarket[1] = 1 and shortonmarket and countofshortshares < countofshortshares[1]) or (shortonmarket[1] = 1 and shortonmarket and countofshortshares > countofshortshares[1]) or (longonmarket[1] and shortonmarket) or (shortonmarket[1] and longonmarket) Thenoptimize = optimize + 1EndIfIf monthinit = 1 or monthinit = 3 or monthinit = 5 or monthinit = 7 or monthinit = 8 or monthinit = 10 or monthinit = 12 ThenMonthDays = 31ElsIf monthinit = 4 or monthinit = 6 or monthinit = 9 or monthinit = 11 ThenMonthDays = 30ElsIf monthinit = 2 ThenIf (yearinit/4 = round(yearinit/4)) or (yearinit/400 = round(yearinit/400)) Then //haha not sure how exactly to do thisMonthDays = 29 //leap yearElseMonthDays = 28EndIfEndIfIf (month = monthinit and day = dayinit + ResetPeriod) or (month = monthinit + 1 and (day + (MonthDays - dayinit)) >= ResetPeriod) ThenValueX = StartingValueWinCountB = 0StratAvgB = 0BestA = 0BestB = 0dayinit = daymonthinit = monthyearinit = yearEndIfonce ValueX = StartingValueonce PIncPos = 1 //Positive Increment Positiononce NIncPos = 1 //Neative Increment Positiononce Optimize = 0 ////Initialize Heuristicks Engine Counter (Must be Incremented at Position Start or Exit)once Mode = 1 //Switches between negative and positive increments//once WinCountB = 3 //Initialize Best Win Count//GRAPH WinCountB coloured (0,0,0) AS "WinCountB"//once StratAvgB = 4353 //Initialize Best Avg Strategy Profit//GRAPH StratAvgB coloured (0,0,0) AS "StratAvgB"If Optimize = Reps ThenWinCountA = 0 //Initialize current Win CountStratAvgA = 0 //Initialize current Avg Strategy ProfitHeuristicsCycle = HeuristicsCycle + 1For i = 1 to Reps DoIf positionperf(i) > 0 ThenWinCountA = WinCountA + 1 //Increment Current WinCountEndIf//StratAvgA = StratAvgA + (((PositionPerf(i)*countofposition[i]*100000)*-1)*-1)StratAvgA = StratAvgA + (((PositionPerf(i)*pointvalue)*countofposition[i])/pipsize)NextStratAvgA = StratAvgA/Reps //Calculate Current Avg Strategy Profit//Graph (PositionPerf(1)*countofposition[1]*100000)*-1 as "PosPerf1"//Graph (PositionPerf(2)*countofposition[2]*100000)*-1 as "PosPerf2"//Graph StratAvgA*-1 as "StratAvgA"//once BestA = 300//GRAPH BestA coloured (0,0,0) AS "BestA"If StratAvgA >= StratAvgB ThenStratAvgB = StratAvgA //Update Best Strategy ProfitBestA = ValueXEndIf//once BestB = 300//GRAPH BestB coloured (0,0,0) AS "BestB"If WinCountA >= WinCountB ThenWinCountB = WinCountA //Update Best Win CountBestB = ValueXEndIfIf WinCountA > WinCountB and StratAvgA > StratAvgB ThenMode = 0ElsIf WinCountA < WinCountB and StratAvgA < StratAvgB and Mode = 1 ThenValueX = ValueX - (Increment*NIncPos)NIncPos = NIncPos + 1Mode = 2ElsIf WinCountA >= WinCountB or StratAvgA >= StratAvgB and Mode = 1 ThenValueX = ValueX + (Increment*PIncPos)PIncPos = PIncPos + 1Mode = 1ElsIf WinCountA < WinCountB and StratAvgA < StratAvgB and Mode = 2 ThenValueX = ValueX + (Increment*PIncPos)PIncPos = PIncPos + 1Mode = 1ElsIf WinCountA >= WinCountB or StratAvgA >= StratAvgB and Mode = 2 ThenValueX = ValueX - (Increment*NIncPos)NIncPos = NIncPos + 1Mode = 2EndIfIf NIncPos > MaxIncrement or PIncPos > MaxIncrement ThenIf BestA = BestB ThenValueX = BestAElseIf reps >= 10 ThenWeightedScore = 10ElseWeightedScore = round((reps/100)*100)EndIfValueX = round(((BestA*(20-WeightedScore)) + (BestB*WeightedScore))/20) //Lower Reps = Less weight assigned to Win%EndIfNIncPos = 1PIncPos = 1ElsIf ValueX > MaxValue ThenValueX = MaxValueElsIf ValueX < MinValue ThenValueX = MinValueEndIFOptimize = 0EndIf// Heuristics Algorithm 1 End//ElsIf HeuristicsAlgo2 = 1 Then//Heuristics Algorithm 2 StartIf (onmarket[1] = 1 and onmarket = 0) or (longonmarket[1] = 1 and longonmarket and countoflongshares < countoflongshares[1]) or (longonmarket[1] = 1 and longonmarket and countoflongshares > countoflongshares[1]) or (shortonmarket[1] = 1 and shortonmarket and countofshortshares < countofshortshares[1]) or (shortonmarket[1] = 1 and shortonmarket and countofshortshares > countofshortshares[1]) or (longonmarket[1] and shortonmarket) or (shortonmarket[1] and longonmarket) Thenoptimize2 = optimize2 + 1EndIfIf monthinit2 = 1 or monthinit2 = 3 or monthinit2 = 5 or monthinit2 = 7 or monthinit2 = 8 or monthinit2 = 10 or monthinit2 = 12 ThenMonthDays2 = 31ElsIf monthinit2 = 4 or monthinit2 = 6 or monthinit2 = 9 or monthinit2 = 11 ThenMonthDays2 = 30ElsIf monthinit2 = 2 ThenIf (yearinit2/4 = round(yearinit2/4)) or (yearinit2/400 = round(yearinit2/400)) Then //haha not sure how exactly to do thisMonthDays2 = 29 //leap yearElseMonthDays2 = 28EndIfEndIfIf (month = monthinit2 and day = dayinit2 + ResetPeriod2) or (month = monthinit2 + 1 and (day + (MonthDays2 - dayinit2)) >= ResetPeriod2) ThenValueY = StartingValue2WinCountB2 = 0StratAvgB2 = 0BestA2 = 0BestB2 = 0dayinit2 = daymonthinit2 = monthyearinit2 = yearEndIfonce ValueY = StartingValue2once PIncPos2 = 1 //Positive Increment Positiononce NIncPos2 = 1 //Neative Increment Positiononce Optimize2 = 0 ////Initialize Heuristicks Engine Counter (Must be Incremented at Position Start or Exit)once Mode2 = 1 //Switches between negative and positive increments//once WinCountB2 = 3 //Initialize Best Win Count//GRAPH WinCountB2 coloured (0,0,0) AS "WinCountB2"//once StratAvgB2 = 4353 //Initialize Best Avg Strategy Profit//GRAPH StratAvgB2 coloured (0,0,0) AS "StratAvgB2"If Optimize2 = Reps2 ThenWinCountA2 = 0 //Initialize current Win CountStratAvgA2 = 0 //Initialize current Avg Strategy ProfitHeuristicsCycle = HeuristicsCycle + 1For i2 = 1 to Reps2 DoIf positionperf(i) > 0 ThenWinCountA2 = WinCountA2 + 1 //Increment Current WinCountEndIf//StratAvgA2 = StratAvgA2 + (((PositionPerf(i)*countofposition[i]*100000)*-1)*-1)StratAvgA2 = StratAvgA2 + (((PositionPerf(i)*pointvalue)*countofposition[i])/pipsize)NextStratAvgA2 = StratAvgA2/Reps2 //Calculate Current Avg Strategy Profit//Graph (PositionPerf(1)*countofposition[1]*100000)*-1 as "PosPerf1-2"//Graph (PositionPerf(2)*countofposition[2]*100000)*-1 as "PosPerf2-2"//Graph StratAvgA2*-1 as "StratAvgA2"//once BestA2 = 300//GRAPH BestA2 coloured (0,0,0) AS "BestA2"If StratAvgA2 >= StratAvgB2 ThenStratAvgB2 = StratAvgA2 //Update Best Strategy ProfitBestA2 = ValueYEndIf//once BestB2 = 300//GRAPH BestB2 coloured (0,0,0) AS "BestB2"If WinCountA2 >= WinCountB2 ThenWinCountB2 = WinCountA2 //Update Best Win CountBestB2 = ValueYEndIfIf WinCountA2 > WinCountB2 and StratAvgA2 > StratAvgB2 ThenMode = 0ElsIf WinCountA2 < WinCountB2 and StratAvgA2 < StratAvgB2 and Mode2 = 1 ThenValueY = ValueY - (Increment2*NIncPos2)NIncPos2 = NIncPos2 + 1Mode2 = 2ElsIf WinCountA2 >= WinCountB2 or StratAvgA2 >= StratAvgB2 and Mode2 = 1 ThenValueY = ValueY + (Increment2*PIncPos2)PIncPos2 = PIncPos2 + 1Mode = 1ElsIf WinCountA2 < WinCountB2 and StratAvgA2 < StratAvgB2 and Mode2 = 2 ThenValueY = ValueY + (Increment2*PIncPos2)PIncPos2 = PIncPos2 + 1Mode2 = 1ElsIf WinCountA2 >= WinCountB2 or StratAvgA2 >= StratAvgB2 and Mode2 = 2 ThenValueY = ValueY - (Increment2*NIncPos2)NIncPos2 = NIncPos2 + 1Mode2 = 2EndIfIf NIncPos2 > MaxIncrement2 or PIncPos2 > MaxIncrement2 ThenIf BestA2 = BestB2 ThenValueY = BestAElseIf reps2 >= 10 ThenWeightedScore2 = 10ElseWeightedScore2 = round((reps2/100)*100)EndIfValueY = round(((BestA2*(20-WeightedScore2)) + (BestB2*WeightedScore2))/20) //Lower Reps = Less weight assigned to Win%EndIfNIncPos2 = 1PIncPos2 = 1ElsIf ValueY > MaxValue2 ThenValueY = MaxValue2ElsIf ValueY < MinValue2 ThenValueY = MinValue2EndIFOptimize2 = 0EndIf// Heuristics Algorithm 2 End//EndIf//c1=average[valuex](close)//c2=average[valuey](close)////condbuy =c1 crosses over c2 and rsi[14](close)<70//condsell=c1 crosses under c2 and rsi[14](close)>30////if condbuy then//buy at market//endif//if condsell then//sellshort at market//endif//pp=positionperf(0)*100//if pp<-0.125 then//sell at market//exitshort at market//endif//set stop %loss 0.5 // exit sooner on performance criteria above//set target %profit 0.25graph valuex coloured(121,141,35,255)graph valuey coloured(255,0,0,255)//endifindicator1 = ExponentialAverage[valuex](close)indicator2 = ExponentialAverage[valuey](close)c1 = (indicator1 CROSSES OVER indicator2)indicator3 = WilderAverage[30](close)c2 = (close > indicator3)IF c1 AND c2 THENBUY 1 SHARES AT MARKETENDIF// Conditions pour ouvrir une position en vente à découvertindicator4 = ExponentialAverage[valuex](close)indicator5 = ExponentialAverage[valuey](close)c3 = (indicator4 CROSSES UNDER indicator5)indicator6 = WilderAverage[30](close)c4 = (close < indicator6)IF c3 AND c4 THENSELLSHORT 1 SHARES AT MARKETENDIF// Stops et objectifsSET STOP pLOSS 8SET TARGET pPROFIT 4And I compare the results on 2 graph. But sadly the results are worst with the learning machine
Can you test too with this procedure (I think it’s good) on another simple code: Backtest to determine the “best” values to put in starting values and compare
May be it’s the code or me 🙂 but it’s strange the results are worst
See U Coders
04/28/2020 at 3:09 PM #12864704/28/2020 at 3:15 PM #128650Baloney or interesting?
Paul that is interesting / good blue sky thinking!
If we are persevering with Renko, do we need to try and start the count for box size at the lowest low for x bars or highest high for x bars etc?
If the renko starts counting for box size near the top of a good run up and as the renko strategy allows for a count of 2 x box size before it goes Long … then we may be right near the highest high for x bars and bang we have gone long and just around the corner is a fib retrace coming along.
If we start counting near the lowest low for a Long then we are in with a fighting chance of going into early profit rather than early loss?
Given the limitations of Renko, we could try the ML on the good old Vectorial … I reckon still a good strategy and coming back into fashion now the madness / high volatility seems over for a while?
Renko was great when the ups and downs were long and frequent, but markets have quietened loads in the last 2 weeks?
Just a few thoughts anyway.
1 user thanked author for this post.
04/28/2020 at 3:33 PM #128663Can you test too with this procedure
I didn’t test but see below … your HAlgo2 is using values from HAlgo1 … see the red i’s well they should be i2?
It got screwed up so I made the i’s into iiiiiiii … cant stop sorry as a trade has just popped !!! 🙂
1234567For i2 = 1 to Reps2 DoIf positionperf iiiiii>(<strong>i</strong></span>) > 0 ThenWinCountA2 = WinCountA2 + 1 //Increment Current WinCountEndIf//StratAvgA2 = StratAvgA2 + (((PositionPerfiiiiiiiii(<span style="color: #ff0000;" data-mce-style="color: #ff0000;">i</span>)*countofposition[<span style="color: #ff0000;" data-mce-style="color: #ff0000;">i]</span>*100000)*-1)*-1)StratAvgA2 = StratAvgA2 + (((PositionPerfiiiiiiiiii(<span style="color: #ff0000;" data-mce-style="color: #ff0000;">i</span>)*pointvalue)*countofposition[<span style="color: #ff0000;" data-mce-style="color: #ff0000;">i</span>])/pipsize)Next04/28/2020 at 3:37 PM #128666@GraHal Well both are interesting! With renko what you said about fib.retracement is spot on. Still it’s too early to give up on renko, especially with two boxsizes!
But I say, there’s a difference when to trade the dji. Focus on 8-15(30) to take trades and close at 17.30 or 18. Trading renko when the market is open, results go down. I’am still experimenting but that’s what it looks to me and you have stability with the spread. Also reducing the stoploss is key.
I’ve been running vectorial, optimised for 5s timeframe! Nice backtest, not so nice results live though. 🙂 Not even with ML included!
Probably I will give my idea from above a shot. Gathering parameters from optimisation results, group them and then use ML.
1 user thanked author for this post.
04/28/2020 at 4:18 PM #128677Cheers for the pointer, I knew those equity curves “on tbt” sometimes looked very improbable! I was actually thinking of experimenting with non ML Kase Dev Stops (posted earlier) or Kaufman’s Volatility Stops. This is totally needed now. Might even be worth setting the ML algo on them too (for a Renko ML2 boxsize and stop loss std deviation amount before the stop licks in or lookback period). I will post if I find anything that reliably improves profitability. I think Paul’s v4 Trailing Stop (TS) might offer a solution. I’m going to look at that version later.
With the myriad of opportunities for testing and not enough hours in the day, might be best to really hone in and use the most efficient and predictive indicators/chart patterns and ML those.
Still working on applying ML2 to Renko Boxsizes and the Take Profit amount… with soon to be added different stop losses, ha ha.Not sure yet if it’s best to keep it very simple with just a singe ML system or better to have two ML’s. Still working on that too.
At least v4 ts had this covered.
Paul this is next on my to do list, after clarifying if it’s better to have just an ML1 or an ML2 on the Ehler’s Oscillator, and on Renko’s.
Is the current definition of the Renko that we’ve been using the best definition or did you get better results with a switch between the 3 different types?1 user thanked author for this post.
04/28/2020 at 4:42 PM #128684Re: Renko boxsize GraHal: ( ps/ why can’t I get this comment to say GraHal wrote: )
If we start counting near the lowest low for a Long then we are in with a fighting chance of going into early profit rather than early loss?
How trend dependent is the success of a Renko system if it still makes money in flat markets? Did you see that the Renko system still made profits in flat markets, I showed you how it made money in a flat period for the Dow in Nov 2016 (before the US election). The trailing stop was largish at 100 so the results are not to be totally dismissed like they should be if the stop is 10 ticks, now that we know the trailing stop doesn’t work with tbt testing. I actually can’t wait to open PRT and see how the Kase Dev Stop and Kaufman Volatility Stop fair.
Maybe Finning’s idea of an ATR related boxsize would work too? If somebody could get my code to work!? https://www.prorealcode.com/topic/machine-learning-in-proorder/page/19/#post-128100
04/28/2020 at 4:43 PM #128685Also note that to set starting values to the algorithm all the commented out code which have a ‘once’ as well as a ‘Graph’ command on the line directly below it has to be activated. i.e. once BestA = 300 etc.
I used it to graph and then set the final values generated by the algorithm as the starting values when using the strategy on a live system
04/28/2020 at 4:55 PM #128692Can you test too with this procedure
I didn’t test but see below … your HAlgo2 is using values from HAlgo1 … see the red i’s well they should be i2?
It got screwed up so I made the i’s into iiiiiiii … cant stop sorry as a trade has just popped !!! 🙂
1234567For i2 = 1 to Reps2 DoIf positionperf iiiiii>(<strong>i</strong></span>) > 0 ThenWinCountA2 = WinCountA2 + 1 //Increment Current WinCountEndIf//StratAvgA2 = StratAvgA2 + (((PositionPerfiiiiiiiii(<span style=”color: #ff0000;” data-mce-style=”color: #ff0000;”>i</span>)*countofposition[<span style=”color: #ff0000;” data-mce-style=”color: #ff0000;”>i]</span>*100000)*-1)*-1)StratAvgA2 = StratAvgA2 + (((PositionPerfiiiiiiiiii(<span style=“color: #ff0000;” data–mce–style=“color: #ff0000;”>i</span>)*pointvalue)*countofposition[<span style=“color: #ff0000;” data–mce–style=“color: #ff0000;”>i</span>])/pipsize)NextThanks Grahal,
I made the correction (as the rep was the same the results was the same)
And I compare your version on page 3, Paul version on pp 20 and Brad version on pp 22 and the results with the same value (4;30) and same code are quite different …
04/28/2020 at 5:18 PM #128701why can’t I get this comment to say GraHal wrote
Because you need to select the text you want to Quote THEN select the word Quote on the toolbar … see the red arrowhead on attached.
I’m glad that’s sorted, but no worries … we got there in the end!? 🙂 🙂
1 user thanked author for this post.
-
AuthorPosts
Find exclusive trading pro-tools on