0
$\begingroup$

First, I have to say sorry - my question is very basic. I do not have a good understanding of math and statistics. I did a lot of research before posting here, but I could not come to a 100% satisfying answer to my problem. Here is my situation:

So there is this pretty neat financial website which shows me the 250 and 30 day Volatility in % of a certian stock on a certain stock exchange.

And I have this pretty neat C# code which calculates the Standard Variation for a given return array.

I also have all CLOSE prices of the last 250 trading days for this asset on that stock exchange. When I run my C# logic over all calculated returns the result matches exactly the figure I can see on that website - 40.8 % for the 250d Volatiliy.

So far so good.

But when I run the same Code handing over the returns of only the last 30 trading days, it comes up with 6.6% - instead of the figure for 30d on that website which is around 20.07%.

So I guess I am doing something wrong. I searched many websites to find the correct approach to calculate the figure correctly, but I did not manage to get a result which is close to 20.07%.

The closest approach I have is this: I am guessing the 30d figure on that website is the annualized volatility. So I thought I have to multiply my result of 6.6% with the the respective multiplier which I learned should be the Square Root of 250 / 30. The result in this case is 19.05% - which is not 20.07% obviously.

Could someone please tell me if my approach is correct or not? It could of course be that the website does not take the CLOSE prices to calculate the volatilites, that would be an explanation. I just want to know if my approach is correct.

EDIT: Code for calculation of Volatility (not written by me):

    public static class Volatility
{
    public static double stdDeviation;
    public static double semiDeviation;

    public static void CalcVolatility(List<float> returns, Predicate<int> filter)
    {
        double tempStandard = 0;
        double tempSemi = 0;
        int count = 0;

        double averageLogReturn = logAverage(returns, filter);

        for (int ii = 0; ii < returns.Count; ii++)
        {
            if (!filter.Invoke(ii))
                continue;

            double logReturn = Math.Log(1 + returns[ii]);
            double add = Math.Pow(logReturn - averageLogReturn, 2);

            tempStandard = tempStandard + add;
            count++;

            if (logReturn < averageLogReturn)
                tempSemi = tempSemi + add;
        }

        stdDeviation = Math.Sqrt(tempStandard/(count - 1)*count);
        semiDeviation = Math.Sqrt(tempSemi/(count - 1)*count);
    }

    private static double logAverage(List<float> returns, Predicate<int> filter)
    {
        double sum = 0;
        int count = 0;

        for (int ii = 0; ii < returns.Count; ii++)
        {
            if (!filter.Invoke(ii))
                continue;

            sum += Math.Log(1 + returns[ii]);
            count++;
        }

        return sum/count;
    }
}

Here is the list of returns, starting with the oldest:

-0.02970294,-0.03061228,0.03157898,-0.0204082,-0.05208328,-0.02197807,-0.02247189,-0.02298848,0,0.03529408,0.01477274,-0.04703247,0.04347826,0.007882848,-0.002234608,-0.03919376,0.04895104,0.00777781,-0.0154355,0.003359486,-0.03236612,0.00922724,-0.03428568,0.02958577,-0.00114941,-0.02991947,-0.007117417,0.01194742,-0.005903182,0.01781471,0.002333762,0,-0.01979048,0.00356297,-0.004733737,0.009512433,-0.01295639,-0.002386604,-0.01315794,-0.001212106,-0.01820387,0.0321384,0.03113775,0.00464577,0.004624287,-0.01726127,-0.02341918,-0.002398051,0.01322113,-0.01542113,0.03734942,-0.01858301,-0.002366904,-0.03084226,-0.02692773,-0.04905665,-0.003968203,-0.01859229,0.04194852,0.02987013,-0.001261018,0.003787905,0.04402512,-0.1638554,-0.03458212,0.04626859,0.03708991,0.01100415,-0.0122449,0.0247934,-0.001344149,-0.1184388,-0.0396946,0.02543716,0.007751931,-0.01230763,0.01713392,0.02143951,0.001499231,0.002994063,0.03432836,-0.01731605,0.005873727,0.01605836,-0.02586208,0.07669624,0.04931501,-0.03263704,0.0202429,0.002645548,-0.02506595,-0.01082546,0.02188779,0.02275772,0.003926729,-0.01434164,0.001322813,0.03698811,-0.003821683,0.003836344,-0.02929937,0.02362198,0.03076929,-0.01368164,-0.01639346,0.001282111,0.03072982,-0.004968954,0.008739113,-0.001237682,0.01239156,0.002448022,-0.006105,0.001228485,-0.007361942,-0.00247223,-0.001239141,0.003722111,-0.01606924,-0.006281401,0,-0.05183313,-0.009333372,-0.0107671,-0.01360543,-0.001379375,0.02762437,0.03494618,-0.012987,-0.02894739,-0.009485054,0.02462381,0.005340465,-0.04913678,0.03212291,-0.01894452,-0.001379375,-0.006906071,0.02503478,-0.02713702,-0.01394699,-0.01414426,0.02439019,0.02380955,0.03146375,-0.007957536,0.01069513,0.02116407,0.01295335,0.0102302,0.01012653,-0.03007518,0.01162791,0.00638569,0.001269019,0.001267486,-0.02151901,-0.03104785,0.01068093,0,-0.02113611,-0.01349526,-0.02872781,-0.02535212,0.008670582,0.007163317,-0.004267455,-0.01714281,-0.03052329,0.04647679,0.002865293,0,0.01571434,-0.02531646,0.007215,0.01575928,-0.004231341,0.01558079,-0.009762942,-0.02957742,0.08708273,0.01735649,-0.001312397,-0.01314059,0.01597873,0.009174271,0.02337663,0.0177665,0.03241898,0.01086957,0.001194728,-0.0250597,0.04406366,0.01992968,-0.04022992,0.008383268,0,0.01068884,0.003525219,0.00234196,-0.003504697,-0.01289564,-0.02969125,0.01223996,0.02055618,-0.005924165,0.01549465,-0.01877931,-0.01196178,0.01089589,0.007185679,-0.007134413,-0.001197589,-0.01678657,0.001219496,-0.02436051,-0.02996253,0.01673103,0.005063301,0,0.0201511,0.02962962,-0.02637891,0.01354684,-0.01579588,0.007407385,-0.006127445,-0.01356347,-0.01125,0.002528413,-0.01513236,-0.007682512,-0.006451607,-0.012987,0.01710528,-0.02328591,0.01456951,-0.006527409,0.01445471,0.01683939,0.001273869,-0.007633641,0.002564146,-0.01406647,0.01426716,0.007672612,-0.002538038,-0.008905889,0.005134799,0.02043427,0.01376718,0.004938282,0.002456971,0.007352993
$\endgroup$
  • $\begingroup$ Annualization is the correct approach (I would have used 252 instead of 250 but this makes little difference). The reason for the discrepancy between 19.05% and 20.07% is not clear from your information and requires further investigation. $\endgroup$ – noob2 Mar 22 '17 at 13:21
  • $\begingroup$ Thank you for the confirmation that I am not completely wrong. $\endgroup$ – flo Mar 22 '17 at 13:53
  • $\begingroup$ @flo Better off writing your own code and being sure it is correct. The portion of the above code that calculates the stdDeviation does not appear to be correct unless I'm misreading it. $\endgroup$ – amdopt Mar 22 '17 at 18:49
  • $\begingroup$ @amdopt: I trust the code because it gives me the expected result for the 250 days period. $\endgroup$ – flo Mar 22 '17 at 19:12
0
$\begingroup$

Could someone please tell me if my approach is correct or not? It could of course be that the website does not take the CLOSE prices to calculate the volatilites, that would be an explanation. I just want to know if my approach is correct.

The correct approach is as follows: For 1 month historical volatility using a 250 (I use 252) day trading year you would not use the past 30 trading days. 30 days would correspond with a 360 or 365 day trading year. You should use 20 trading days. This is an Excel formula that I just so happen to have open on my desktop right now. Hope it helps.

[Std Dev of Daily Returns of the last 20 trading days]*[Square Root of 252]
=(STDEV.P(I2807:I2826))*SQRT(252)

To calculate HV you need daily % changes. If your source isn't using the closing price to derive their daily % change then they do not have correct HV for the security you are referencing and you will not come up with the same number.

$\endgroup$
  • $\begingroup$ Thank you very much, that is interesting. I will try that out later at home where I have the data. $\endgroup$ – flo Mar 22 '17 at 13:54
  • $\begingroup$ @amdopt: If I use your code approach I get an very high volatility number even when I use only the last 20 trading days: 0.05 * Sqrt(252) = 0.79 = 79 % volatility. I will add the code I use for calculating the Volatiltiy in my original post so maybe there is something wrong with the code itself. $\endgroup$ – flo Mar 22 '17 at 17:20
  • 1
    $\begingroup$ @flo If you are able to share the security I can look up the data myself and help you out further. For the avoidance of doubt though, you should be taking the STDEV of the daily return and not the closing prices. $\endgroup$ – amdopt Mar 22 '17 at 17:27
  • 1
    $\begingroup$ Also keep in mind some people use logarithmic returns and some people (not me) use arithmetic returns in the STDEV. $\endgroup$ – noob2 Mar 22 '17 at 17:43
  • $\begingroup$ I now added the list of returns to my original post. I am sorry I made a mistake in the original post regarding the close prices: What I meant is I calculated the returns BASED on the Close Prices. $\endgroup$ – flo Mar 22 '17 at 19:14
0
$\begingroup$

It's quite difficult to replicate without the data and the website you mentioned.

It is likely that the 20% is annualized (since that is a rather standard way of presenting it), so your 19% isn't too far off. Some possible reasons there's a difference may be:

  • Your data is using EOD close price while the website isn't
  • One dataset adjusts for stock splits, shares, repos, etc while the other doesn't
  • Possible error in the C code
  • Possible error in the website code
$\endgroup$
  • $\begingroup$ Thank you for your comment on my issue. I will take the figure from my Code since it is not so far off as you said. $\endgroup$ – flo Mar 23 '17 at 13:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.