none
How to repeat a task multiple times without repeating the formulas? RRS feed

  • Question

  • I have this task i want to reproduce. CMA represent an average, for exemple 20. As the average is moving it increase to 21, 22, 23 etc. I would like to produce a simulation for each price of the moving average. As you can see the price is passing through a series of formulas and at the end closest return a value. It returns one value. I want to be able to test each cma returns, 21, 22, 23 separately and get to keep the returns for each cma in a list or variable. Right now if i replace cma by Price (21,22,23 etc) at the end of the code closest will return one answer for all the prices and not one return per prices or cma's. Anyone as an idea how to do that? I was thinking about switch and cases but dont know how to implement them.

    Thank you

    for(int barIndex = index; barIndex <= ChartBars.ToIndex; barIndex++)
                    {
            
         double Price = Bars.GetClose(barIndex); 
        
         sumvolms += vols;
         
       
          if(cma < highPrice && cma > lowPrice)
           {  
            for(int myIndex = index; myIndex <= barIndex; myIndex++)
                          {
               
                          }
          
                              
                    
             List<double> zlist = new List<double>() {sumvolms};
            
             for(int z = 0; z < zlist.Count; z++)
                {
             zlist[z] = (zlist[z] /= sumvols);

    //more formulas than returns end up in a list//

    var list = zlist.Union(alist)
                              .Union(blist)
                              .Union(clist)
                              .Union(dlist)

     .ToList(); 

    //lambda search closest number from variable in list//

    double minDistance = list.Min(no => Math.Abs(fibo1- no));
    closest = list.First(no => Math.Abs(fibo1- no) == minDistance);

    //closest should return one answer per prices or cma but return only one instead of one value per prices//


    Monday, September 23, 2019 12:25 PM

All replies

  • Please put code into code blocks using the Insert Code Block tool in the toolbar of the editor. It is hard to read code without it.

    If you need to repeat some code then put it all into a function. Then you can pass in the data (via parameters) you want to change each time the function runs. If the code returns a value then return that from the function and store it somewhere. Unfortunately you are using acronyms and have posted code that is not very readable so it is hard to see exactly what part of your code is relevant to your discussion and what you consider to be the reusable logic. So here is just a sample.

    for (int barIndex = index; barIndex <= ChartBars.ToIndex; barIndex++)               
    {
      //Ignoring all this as it doesn't seem relevant
      double Price = Bars.GetClose(barIndex);     
      sumvolms += vols;     
       
      //Seems like the part you actually care about
      if(cma < highPrice && cma > lowPrice)
      {
         //Not sure what to do with the returned value though
         var someValue = GetSomeValue(index, barIndex);
      }     
          
      //Ignoring the rest of the code
    }
    
    //Reusable stuff - can test this code
    double GetSomeValue ( int startIndex, int endIndex )
    {
       //Reusable code goes here
       for (var index = startIndex; index <= endIndex; ++index)
       {
       };
    
       //Return something
       return 123.45;
    }
    Personally, if you want to play around with code like this I think you need to normalize it some more so you can control the inputs rather than relying on the existence of ChartBars and whatnot. Make this stuff parameters to the function(s) so you can pass in custom values to do your "what-if" logic more easily. For example if you didn't rely on ChartBars then you could pass in arbitrary sets of values to verify the behavior of the function.


    Michael Taylor http://www.michaeltaylorp3.net

    Monday, September 23, 2019 1:54 PM
    Moderator
  • Hello,

    I just noted that some of my code dont do what i was expecting. 

    That part loop through all the uptrend bars in the chart.

    for(int barIndex = index; barIndex <= ChartBars.ToIndex; barIndex++)               
     {     
    
    double Price = Bars.GetClose(barIndex); 

    The CMA return a moving average like 23.

    The If statement check in the uptrend all bars that are about equal to the CMA 23.

    Than my goal was to get all the bars from the bottom of the trend to the bars that are about equal to the cma (23) and sum them.

    That's where is coming the second for loop. But the result dont sum from bottom to each bar where it equal cma, it sum from bottom of the trend to the last bar that cross the cma:

    if(cma < highPrice && cma >lowPrice)       
    
    {                
    for(int myIndex = index; myIndex <= barIndex; myIndex++)        
    
    {          
    
    double vols1 = Bars.GetVolume(myIndex);                      
    
    sumvolms += vols1;                         
    
    
    Print(sumvolms);
    
    }

    That part is bugging me and until it is resolve i want be able to fix the rest.

                                 



              

    Monday, September 23, 2019 2:42 PM
  • I don't understand what cma, uptrend all bar, bottom of trend, etc all mean. Please refer to the code you posted and indicate which variables are not behaving like you want and what they should be doing.

    Michael Taylor http://www.michaeltaylorp3.net

    Monday, September 23, 2019 2:49 PM
    Moderator
  • for(int barIndex = index; barIndex <= ChartBars.ToIndex; barIndex++) { double Price = Bars.GetClose(barIndex); sumvolms += vols;

    //suppose cma = 22, the if statement is looking for every price that match 22//

    if(cma < highPrice && cma > lowPrice) { for(int myIndex = index; myIndex <= barIndex; myIndex++) { } List<double> zlist = new List<double>() {sumvolms}; for(int z = 0; z < zlist.Count; z++) { zlist[z] = (zlist[z] /= sumvols);

    // there are more formulas that follows but cant write more than 60 000 characters//

    //after it pass all the formulas it returns many % like 0.62, 1.5, 0.85 etc//

    var list = zlist.Union(alist) .Union(blist) .Union(clist) .Union(dlist) .ToList();

    //the list above merge all the returns from the formulas//

    //lambda search closest number from variable in list//

    double minDistance = list.Min(no => Math.Abs(fibo1- no)); closest = list.First(no => Math.Abs(fibo1- no) == minDistance); //closest returns in its actual form one answer for exemple the closest from fibo1 in the list 0.89//

    If i replace CMA by Price that contains more than one value like 25, 26, 27 instead of just 22, closest will still return one value because lambda is looking for the closest one of fibo1 in the list.

    I want to be able to test 25, 26, 27 and get the return value for closest for each Price.

    Meaning 25 should return .85

    26 should return 0.99

    27 should return 1.56

    etc

    Is it possible to change the value at the top of the code and get individual return for each different values without repeating the whole code every time?

    Thank you

    Monday, September 23, 2019 5:36 PM
  • So given Price which is IEnumerable<int> containing, in your example, (25, 26 27) you want to run the `list.First(...)` code that returns `closest` on each value? 

    At no point in your code does `cma` get used in any of the calculations leading up to `closest`. So at this point the actual value wouldn't matter. You mention that `Price` would replace `cma` but where in the formula(s) does `cma/price` actually impact anything? If this value never impacts the formula then each value (for price) would produce the same result. However I assume that somewhere in the formula(s) you left out `cma` (and therefore `price`) impact things. It is at this point that you cannot reuse the values directly. Let's assume this.

    //Don't care where this comes from
    var cma = 22;
    
    //Helper function to get rid of that logic
    var zlist = GetZList(); 
    
    //Formulas that don't rely on cma
    ...
    
    //Formulas that do rely on cma
    ...
    
    //Finish things up
    var list = ...ToList();
    var minDistance = ...;
    var closest = list.First(...);
    

    Let's split this logic up into non-CMA and CMA-dependent code.

    //Don't care where this comes from
    var cma = 22;
    
    //Build up data not related to CMA...
    var data = GetNonCMA();
    
    //Now we care about CMA
    var closest = GetClosest(data, cma);

    Anything that relies on the value of `cma` has to be recalculated each time its value changes so breaking it out into a separate function makes sense. Now converting `cma` to a series of values (`prices`) becomes easy.

    //Don't care where this comes from
    //var cma = 22;
    var prices new int[] { 25, 26, 27 };
    
    //Build up data not related to CMA...
    var data = GetNonCMA();
    
    //Get a value for each
    var results = from price in prices
                  select new { Price = price, Closest = GetClosest(data, price);
    
    //Now have the price and closest values together


    Michael Taylor http://www.michaeltaylorp3.net

    Monday, September 23, 2019 5:52 PM
    Moderator
  • Prices contains all the prices in the for loop.

    var prices new int[] { 25, 26, 27 };

    just confirm that.

    closest at the end will only return the value for all prices globally 

    { 25, 26, 27 } and not the closest number for 25, 26, 27. 

    closest is returning in this case 0.85 when it should be returning the closest number for 25; 0.85 closest number for 26; 0.99, closest number for 27; 1.5 for exemple.

    Is it not the same to do

    var prices new int[] { 25, 26, 27 };var results = from price in prices              select new { Price = price, Closest = GetClosest(data, price);

    Than just replace cma by Price? Will it treat each prices individually?

    Suppose your solution is working i am scratching my head how to implement that.

    Monday, September 23, 2019 6:35 PM
  • I have no idea how you're "closest" logic works so I cannot answer as to why you're getting a different value than expected. You're going to have to step through that code in the debugger and figure it out based upon your understanding of the rules.

    As for the code I posted it demonstrating taking a list of prices and calling your closest logic on each one. The result is a list of prices and the value calculated by your function. So you'd get (25, ?), (26, 0.85), (27, 0.99). Again, if the returned closest isn't correct then that is a logical error in your function you'll need to fix. Since I don't understand that algorithm I cannot help you there. Stepping through the code should allow you to fix it.

    As for the code I posted, my thought is that the final block of code I posted would be a replacement for that code you originally posted. Since I don't have visibility into all the pieces that occur outside that code you'd have to manipulate the logic to work for your situation. It was really just trying to convey that you move the code that isn't reliant on the loop variant (each of your prices) outside your loop, execute that logic once and then inside the loop only put the code that needs to be rerun each time through the loop (aka anything that relies on price). 


    Michael Taylor http://www.michaeltaylorp3.net

    Tuesday, September 24, 2019 1:45 PM
    Moderator
  • Thank you for your help. Its probably me that is not explain things correctly. I have to admit its hard to find a solution when you are not sure where rely exactly the problem.

    closest variable find the closest number near the variable fibo. fibo return a number like 1.2. So if in the large list that gather all the returns from the formulas there is 1.19 than closest will find it. There is no problem there.

    If at the beginning of the pipeline i change the value of cma to any numbers, than it will impact on the results of the formulas and at the end of the pipeline closest will return a different number like 1.17. 

    Entering different numbers to replace the cma like 25, 26, 27 will impact on the return value of closest at the end.

    Unfortunately, it is not possible to enter  25, 26, 27 at the same time using Price variable in the for loop because at the end closest will still return one number and not 3 numbers; one single result for each prices 25, 26, 27.

    I was hoping there was a method i dont know yet that would allow me to enter 25, 26, 27 for exemple and closest would return for exemple 1.17, 1.18, 1.19.

    Right now the only way i see, would be to replace cma by 25 and get the result at closest. Than copy/paste the whole code and replace cma by 26 and get the result at closest1, etc for all other prices. That is an unproductive way to work. You must rename all the variables.

    The code is doing what it is suppose to do. I just want to modify it to keep the result of closest for every prices that will replace cma.

    Tuesday, September 24, 2019 5:32 PM
  • "Unfortunately, it is not possible to enter  25, 26, 27 at the same time using Price variable"

    I assume you mean that if Price were an array (containing 25, 26, 27) then your loop would work but the end result of closest would be the same value in each case.

    "I was hoping there was a method i dont know yet that would allow me to enter 25, 26, 27 for exemple and closest would return for exemple 1.17, 1.18, 1.19"

    There is, it is the Select method provided by LINQ. Given a series of values you can return a new series of values based upon an arbitrary expression. Example.

    var prices = new [] { 25, 26, 27 };
    
    //Get the discounted prices
    var discountedPrices = from p in prices
                           select p * 0.20;
    
    //Or if you want them correlated use an anonymous type
    var discountedPrices2 = from p in prices
                            select new { Price = p, DiscountedPrice = p * 0.20 };

    Again, in the code you posted I don't see anything that relies on cma's value. Therefore `closest` will have the same value whether `cma` is 25, 26, 27. If it does return different values each time then it is that logic that you should move into a helper method, then wrap it in the for loop. Let's start with the basics.

    double GetClosest ( double cma )
    {
       //Put all your formula logic here
    }

    I'm guessing on the types here but take all the code that is working correctly with cma and put it into a helper function. Any place you rely on data outside the function itself needs to be passed in as parameters. At a minimum this would be what you're calling `cma`. Then in your code you originally posted replace all that formula stuff with a call to the function.

    var cma = 25;
    
    var closest = GetClosest(cma);

    Does this produce the value you expected? If so then change `cma` to 26 and verify again. Does it still work? If so then you have successfully made it into a reusable function. If it doesn't then step through your code and fix the errors until it returns the correct value. Note that you may need to demote some variables you are relying on in the formulas from fields (of the type) to local variables or pass them in as parameters. Everything in that function needs to rely on either values it calculates internally or data it is passed in as part of the function call.

    Once you have this function working for a single value, every time then you can add in the multiple values logic with a loop or LINQ.

    var prices = new [] { 25, 26, 27 };
    
    //Using a loop - identical to previous code except you're now calling it once per element in an array
    foreach (var price in prices)
    {
       var closest = GetClosest(price)
    };
    
    //Alternatively you want to keep the original value and calculated values together so use LINQ and a separate type
    
    var results = from p in prices
                  select new { Price = p, Closest = GetClosest(p) };
    The point is that once you have a function that returns the correct output for each input you give it then it is easy to call it for a set of values using a foreach or LINQ.


    Michael Taylor http://www.michaeltaylorp3.net

    Tuesday, September 24, 2019 5:54 PM
    Moderator
  • "I assume you mean that if Price were an array (containing 25, 26, 27) then your loop would work but the end result of closest would be the same value in each case."

    Price dont need to be an array, if i replace cma by Price it will generate more answers. Price equal all the prices in the trend (25,26,27 etc.)

    after passing through all the formulas the list will return 3 times the number of results because there is 3 numbers (25,26,27) 

    Replaced individually 

    25 could return: 1.2 , 1.4, 1.6

    26 could return: 1.3 , 1.7, 1.9

    27 could return: 1.4, 1.6, 2.1

    but closest will choose the nearest number from fibo, if fibo return 1.7, closest will return 1.7

    When in fact it should be returning 1.6, 1.7, 1.6 if we replace cma by Price one by one.

    Now Select clause, the way i see it, will filter from the top in Price 

    From the exemples they are showing here:

    https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/select-clause

    Select will filter inside Price, for exemple i want to eliminate price above 28 in the list. But from what i just tried it is not returning more than one result in closest variable, same for foreach.

    By the way CMA does have an impact in the process. if statement chose the prices in the trend that are about equal to cma. Than it sum the volume between lowest price and the prices = to cma. After that they are processed in the formulas. 

    Maybe you are right its just that i try to see how i could do that and i need to think about it.

    Tuesday, September 24, 2019 6:49 PM