Announcement

Collapse

Looking for a User App or Add-On built by the NinjaTrader community?

Visit NinjaTrader EcoSystem and our free User App Share!

Have a question for the NinjaScript developer community? Open a new thread in our NinjaScript File Sharing Discussion Forum!
See more
See less

Partner 728x90

Collapse

Calculating Risk on Forex Pairs

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    #16
    Originally posted by Unsuitable View Post

    EUR/USD: No conversion needed
    USD/CAD: Multiply the position size by the USD/CAD
    CAD/CHF: Find the forex pair that has USD and CHF. This case USD/CHF. Since USD is the base pair, multiply the positions size by USD/CHF
    EUR/GBP: Find the forex pair that has USD and GBP. This case GBP/USD. Since USD is the quote pair, divide the positions size by GBP/USD
    So I would say above... you definitely have correct WHICH USD pairs to use and WHY(these are the seven data series we have to add), along with understanding how I have separated the CASES. But as for the formula, I am not sure what you mean by "Multiply the position size?"

    So to keep it simple, I would suggest that the formulas I posted in the other post would be the easiest to reference, as I KNOW that works.

    If you need to separate out a different value(E.g if you wanted the formula for stopsize), you can just algebraically solve for whatever value you need. Those formulas are below to calculate lot-size/position-size. For reference...
    • myRisk = is the USD dollar amount you would want to risk(E.g... 24.32, would be risking $24.32)
    • myStop = a value in number of pips. Not pipettes, but pips. So if on your tool it spanned a distance on Eur/Usd from 1.2020 to 1.2010... that would represent a value of 10
    • decimalVal = 0.01 for any pair containing JPY, and 0.0001 for all other pairs
    • exchangeRate = represents the appropriate USD pair price you have to multiply or divide by(the seven added dataseries)

    Code:
    lotSize =  (myRisk/myStop) * (1/decimalVal) ;
    lotSize =  ((exchangeRate * myRisk) / myStop) * (1/decimalVal) ;
    lotSize =  ((myRisk/exchangeRate )/myStop) * (1/decimalVal) ;
    lotSize =  ((myRisk*exchangeRate )/myStop) * (1/decimalVal) ;


    Originally posted by Unsuitable View Post
    As mentioned, other sets of data series need to be added if the account is in a different currency. For now, USD will be the only thing supported with others added later. There should be a check if the USD data sets should be added in the first place, in case that it's not forex and its futures. Hmm, what about futures that are not based in USD? Well all CME instruments are based in USD no?
    I haven't thought much about futures in years... but I would imagine this would be simpler... as futures are fixed, and you should be able to get the per/tick or per/point value from the MasterInstrumentClass HERE.


    Originally posted by Unsuitable View Post
    I guess all currencies have to be added but programmatically only the ones required should be added which will be interesting to figure out. Maximum 2 data series should be added at a time.

    Thanks again for the help! Was shooting in the dark as seemingly no websites to calculate position talk about it. They say, "use this calculator to figure it out".
    Yeah... it would be nice to only load the series you would need on a given chart. If you do implement this at some point, be sure to post about it... as I'm not sure if you can conditionally load select series based on a user input, as State.Configure loads upon initiall addition of an indicator... but maybe it could be hardcoded based on the instrument?

    For example, if you detect on initial load that the pair is Eur/Gbp... you could have a long IF, or SWITCH statement that would ONLY load the Gbp/Usd as the additional series.
    Last edited by forrestang; 02-28-2021, 02:18 PM.

    Comment


      #17
      Hello forrestang,

      My indicator outputs in units. Initially, they were off but by multiplying or dividing the "raw" position by the relevant currency pair I get the correct size. See post #5 for how the indicator calculates the unit position. This way no hard values are used so there's no need for JPY conversion. Does that mean the absolute risk in $ can change by the time the market fills the order? Cause the other currency pair could change price between initially placing the order and it getting filled.

      As for adding only the relevant data series, I was thinking of a switch statement as well. So grab the quote pair of the current instrument and the currency of the account. Then scan for a forex pair that contains both. Perhaps a 2 dimensional for loop should be used. We'll when I get there.

      Thanks
      Unsuitable
      NinjaTrader Ecosystem Vendor - Ocean Trading Indicators

      Comment


        #18
        Hello forrestang,

        Took a crack at it and it's pretty much solved. The only part left is to implement the adding of the dataSeries the final calculations. Here's the method I used.

        1. Calculate the risk. This will be considered the raw unit size and we'll have to check if it needs to be converted (as in multiplied or divided by another currency). It will check if it needs to be converted based on booleans that were set when the chart first loaded. Computing whether it should each time is a waste of resources so do it once and store the values.

        The logic for the booleans

        2. Get the current chart and verify if it's quote or base pair relative to "USD" (up to you if you want to hard code this value). If so then pretty easy, base pair multiply it, quote pair do nothing.

        3. If it's neither, cycle through a string[] that contains all of the pairs. Check if it contains "USD" AND the base pair OR quote pair. If there's a match then that's the "conversion" forex pair and add that data series.

        4. Check whether the conversion forex pair is the base or quote pair relative to "USD" and do the relevant calculations.

        That's pretty much it. Hope this helps!
        Unsuitable
        NinjaTrader Ecosystem Vendor - Ocean Trading Indicators

        Comment


          #19
          Hello forrestang,

          Did you run into any problems getting the price from a data series? Made sure that the data series was added in State.Configure and it's giving the wrong value. I tried to start a new thread with this question and it doesn't seem like the question is getting through and you're familiar with the use case.

          Thanks
          Unsuitable
          NinjaTrader Ecosystem Vendor - Ocean Trading Indicators

          Comment


            #20
            Originally posted by Unsuitable View Post
            Hello forrestang,

            Did you run into any problems getting the price from a data series? Made sure that the data series was added in State.Configure and it's giving the wrong value. I tried to start a new thread with this question and it doesn't seem like the question is getting through and you're familiar with the use case.

            Thanks
            I saw your other thread. I did not have any issues.

            I see you added it in the same basic way that I did also. E.g., AddDataSeries("USDCHF");

            Are you printing this out in onBarUpdate(), or in onRender() or some other method?

            Did you ensure you have the same data loaded? Try printing out the Time[0] with it, to be sure you are looking at the same data.... Something like:
            Code:
            Print(Time[0] + "  " + Closes[1][0] );
            Just a suggestion in the case you're getting some funky data loading.

            Comment


              #21
              Hello forrestang,

              I'm questioning the overall logic of using the current price as the "conversion" price. What about bid vs ask, how does that play into it?

              P.S. I tried the solution in the other thread and it worked... after rebooting NT that is.

              Thanks
              Unsuitable
              NinjaTrader Ecosystem Vendor - Ocean Trading Indicators

              Comment


                #22
                Originally posted by Unsuitable View Post
                Hello forrestang,

                I'm questioning the overall logic of using the current price as the "conversion" price. What about bid vs ask, how does that play into it?

                P.S. I tried the solution in the other thread and it worked... after rebooting NT that is.

                Thanks
                I saw your other question about implementing at run-time... yeah I don't think that's going to be possible, reliably. I did something similar before and got unexpected/random results.

                It is my idea to just hardcode the necessary series need per instrument, and would be easy to do. You do this in State.Configure before the indicator actually starts the onBarUpdate().

                I.e., something like
                Code:
                if (Instrument.MasterInstrument.InstrumentType == InstrumentType.Forex)
                {
                  if(Instrument.FullName.ToString() == "EURGBP"
                  {
                    AddDataSeries("GBPUSD");
                  }
                  elseif( add each instrument here) //There would be a statement for each one necessary
                  {
                   AddDataSeries(etc)
                  }
                {
                I haven't tried the above yet, as I hadn't really found the need, as my sizer does what I need it to. But that's what I am thinking it would be like.

                About using difference prices... it depends on the accuracy you are going for. When I first built mine, I obsessed about that too. But you're talking fractions of pennies. A unit is a TINY amount of size. I don't think practically it will make much difference if you use the bid or ask price, when ur talking a spread of two tenths of a pip or so. I think you can convince yourself of this by putting this into babypips and looking at different dollar values.

                I dont even think babypips has accuracy down to the pipette if I remember correctly? IMO, just got either bid, ask, or just use the last price. But, of course if you NEED to, those values are not difficult to grab.

                Maybe this might be a difference for some million dollar trader, but even then I doubt it.

                You can convince yourself of this by going to babypips and

                Comment


                  #23
                  Hello forrestang,

                  I saw your other question about implementing at run-time... yeah I don't think that's going to be possible, reliably. I did something similar before and got unexpected/random results.
                  For now, the code adds the relevant forex pair dynamically. It seems to be working just fine. In fact, the values "are hardcoded". I have a string[] of all the correct possible values, it's not user input. Beyond that it checks if the string is null or "NONE_FOUND" before adding the data series. "NONE_FOUND" is the string if the logic somehow has USD as both the quote and base pair. Shouldn't be possible, but who knows. Trying to think of a case where it will break. A data series only get's added based on the values pulled from the string[]. In the case where the logic is faulty and selects the wrong conversion pair, it will still give a currency that actually exists.

                  Also, I use the following to obtain the instrument. I noticed some CFDs were under forex which would be incorrect. However, even it accepts a CFD, it won't be able to find the conversion pair. In actuality, Instrument.MasterInstrument.InstrumentType == InstrumentType.Forex and Instrument.FullName.ToString() is superior. The current method is going to compare any instrument. It will only check once, but still. It has to iterate over the entire string[].

                  forexString = ChartControl.Instrument.MasterInstrument.ToString( ).Substring(0, 6);
                  About the fraction of pennies, even if the code is perfectly "calibrated", by the time price fills the order the conversion pair could have change price. Thus throwing off the unit size from the get-go. So you are right in that regard, it's not worth fussing over.

                  Thanks
                  Unsuitable
                  NinjaTrader Ecosystem Vendor - Ocean Trading Indicators

                  Comment


                    #24
                    So I had a HDD failure a while back, and lost all of my position sizing indies I made. I had to recreate them, but am glad I posted in this thread, I was able to replicate it quickly.

                    This time however, I made it with CONDITIONAL LOGIC so it only adds the additional data series WHEN NECESSARY. I.e., assuming you are calculating position sizing in US Dollars, you don't need to add additional data series when USD is either the base or quote currency.

                    My previous position sizers where built to show ALL the conversions on one chart, so I had to add ALL usd crosses. This one I started with, only adds those necessary to calculate the sizing for the on pair ON THE CHART.

                    At the class level, Added two variables just to split the base and quote currencies:
                    Code:
                    //Program Vars
                    string pair1, pair2;

                    In the OnStateChange()/State.Configure section, I added the conditional logic to load additional data series ONLY WHEN NECESSARY:
                    Code:
                    #region CODE Load Instruments
                    if (Instrument.MasterInstrument.InstrumentType == InstrumentType.Forex)
                    {
                        pair1 = ChartControl.Instrument.MasterInstrument.ToString( ).Substring(0, 3);
                        pair2 = ChartControl.Instrument.MasterInstrument.ToString( ).Substring(3, 3);
                    
                        //Assuming USD is NEITHER pair1 or pair2
                        if(pair1 != "USD" && pair2 != "USD" )
                        {
                           if(pair2 == "AUD" ) AddDataSeries("AUDUSD"); //
                           if(pair2 == "CAD" ) AddDataSeries("USDCAD"); //
                           if(pair2 == "CHF" ) AddDataSeries("USDCHF"); //
                           if(pair2 == "EUR" ) AddDataSeries("EURUSD"); //
                           if(pair2 == "GBP" ) AddDataSeries("GBPUSD"); //
                           if(pair2 == "JPY" ) AddDataSeries("USDJPY"); //
                           if(pair2 == "NZD" ) AddDataSeries("NZDUSD"); //
                        }
                    }
                    #endregion


                    The function to actually calculate position size, inputs the Risk Amount(dollars), Stop size(in pips), Instrument Name("EURGBP"). This function returns a double of the units/position size. This has the 4 cases described earlier in the thread:
                    Code:
                    public double GetPositionSize( double myRisk, double myStop, string myPair )
                    {
                        double lotSize = 1;
                    
                       string part1 = myPair.Substring(0,3);
                       string part2 = myPair.Substring(3,3);
                    
                    //Case 1: Assuming pair2 is USD(not really needed, but adding for uniformity)
                       if(part2 == "USD")
                            lotSize = Math.Round( (myRisk/myStop) * (1/myPipSize) , 0); //4 cases, AU,EU,GU,NU
                    
                    //Case 2: Assuming pair1 is USD
                       else if(part1 == "USD")
                          lotSize = Math.Round( ((Close[0] * myRisk) / myStop) * (1/myPipSize) , 0); //3 cases, UCAD,UCHF,UJ
                    
                       else if(part1 != "USD" && part2 != "USD" )
                       {
                       //Case 3: Assuming NEITHER is USD, but pair 2 has match FIRST in secondary series, e.g., Eur/GBP matches to GBP/Usd...
                          if(part2 == "AUD" || part2 == "GBP" || part2 == "NZD")
                             lotSize = Math.Round( ((myRisk/Closes[1][0])/myStop) * (1/myPipSize) , 0);
                    
                       //Case 4: Assuming NEITHER is USD, but pair 2 has match SECOND in secondary series, e.g., Cad/JPY matches to Usd/JPY...
                          else
                             lotSize = Math.Round( ((myRisk*Closes[1][0])/myStop) * (1/myPipSize) , 0);
                       }
                    
                       return lotSize;
                    }



                    The function call is done via:
                    Code:
                    double lotSizeLong = GetPositionSize(AmountRisked, stopSizeLong, Instrument.FullName.ToString());    //GetPositionSize(30.56, 20, "EURGBP")

                    Comment


                      #25
                      Minor addendum. For use in a regular indicator, it works fine. I went to plug this into a strategy, and worked fine. When I went to use it in the strategy analyzer, it threw an error. Seems it does not like getting the instrument name being described using, "ChartControl.Instrument.MasterInstrument.ToString( ).Substring(0, 3);"... with the 'ChartControl' bit.

                      Simply deleting this works fine.

                      Also of note, there is no need to create global variables at the class level as 'pair1,pair2' as they can just be declared locally in the portion with the conditional statements for which series to add.

                      It would look like this:
                      Code:
                      else if (State == State.Configure)
                      {
                          #region CODE Load Instruments
                         if (Instrument.MasterInstrument.InstrumentType == InstrumentType.Forex)
                         {
                      [COLOR=#e74c3c]      string pair1 = Instrument.MasterInstrument.Name.ToString( ).Substring(0, 3);
                            string pair2 = Instrument.MasterInstrument.Name.ToString( ).Substring(3, 3);[/COLOR]
                      
                            //Assuming USD is NEITHER pair1 or pair2
                            if(pair1 != "USD" && pair2 != "USD" )
                            {
                               if(pair2 == "AUD" ) AddDataSeries("AUDUSD"); //
                               if(pair2 == "CAD" ) AddDataSeries("USDCAD"); //
                               if(pair2 == "CHF" ) AddDataSeries("USDCHF"); //
                               if(pair2 == "EUR" ) AddDataSeries("EURUSD"); //
                               if(pair2 == "GBP" ) AddDataSeries("GBPUSD"); //
                               if(pair2 == "JPY" ) AddDataSeries("USDJPY"); //
                               if(pair2 == "NZD" ) AddDataSeries("NZDUSD"); //
                            }
                         }
                         #endregion
                      }

                      Comment


                        #26
                        My solution to adding only the necessary pairs was to have a string array of all the pairs. Check and divide the chart's instrument into a base and quote pair strings. Based on the quote and base pair, add the appropriate data series if required. And voila, the appropriate series are added. At the same time, that code sets variables to true or false so the program knows it has to do extra steps once calculating the position size.
                        Unsuitable
                        NinjaTrader Ecosystem Vendor - Ocean Trading Indicators

                        Comment

                        Latest Posts

                        Collapse

                        Topics Statistics Last Post
                        Started by Max238, Today, 01:28 AM
                        3 responses
                        30 views
                        0 likes
                        Last Post Max238
                        by Max238
                         
                        Started by timko, Today, 06:45 AM
                        2 responses
                        12 views
                        0 likes
                        Last Post NinjaTrader_ChristopherJ  
                        Started by habeebft, Today, 07:27 AM
                        0 responses
                        4 views
                        0 likes
                        Last Post habeebft  
                        Started by Tim-c, Today, 03:54 AM
                        1 response
                        7 views
                        0 likes
                        Last Post NinjaTrader_BrandonH  
                        Started by rocketman7, Today, 01:00 AM
                        1 response
                        10 views
                        0 likes
                        Last Post NinjaTrader_ChelseaB  
                        Working...
                        X