cos(arccos(x)) just cancels each other, leaving x. Did I give you that formula? If so I made a mistake. Does no harm though as c^2 = a^2 + b^2 - 2ab * cor(a,b) is correct. That looks right. 0.01312 is the var. You want the vol: sqrt(.01312) [1] 0.1145426 or 11.5% Well .115 is not that far from .10 Your real problem in using the triangle relationships discussed in the thread above is that there are no publicly quoted options in KO/PEP and thus no implied vol for the KO - PEP side length of the triangle and thus no implied corr. Measured/estimated corrs and vols are likely to understate the true (if there were such options) numbers. What you might do is assume that the takers (representative agent) in KO/PEP would be operating under the same preference curve (SDF or pricing kernel) as the takers in KO and PEP vanillas. Then derive the SDF assuming isoelastic utility for KO and PEP and apply an average of the two (they should be close) to your KO/PEP vol and corr estimates. Estimate your correlation through intraday realized kernel vars. Small sample corr is hard to measure (as in time-varying corr). Var (vol) has better small-sample estimators (e.g. Yang-Zhang, realized kernel intraday vol...) Even if we attempt a YZ stle corr estimate, we dont know the timings of the highs/lows in EOD bar data, and even if we did, they would likely be non-contemporaneous, leaving you with an asynchronos corr estimation problem. Best solution is to estimate vols/vars from overlapping 5min bar lasts, then convert to corr: rho(a,b) = -.5 * (var(a/b) - var(a) - var(b)) / sqrt(var(a) * var(b)) Code: > h <- rnorm(5000) / 50 > g <- rnorm(5000) / 100 > hh <- cumprod(exp(c(0,h))) > gg <- cumprod(exp(c(0,g))) > sd(diff(log(hh/gg))) [1] 0.02228933 > sd(diff(log(gg/hh))) [1] 0.02228933 > sd(diff(log(hh*gg))) # pretty close! [1] 0.02244188 > rho <- -.5 * (var(diff(log(hh/gg))) - var(g) - var(h)) / (sd(g) * sd(h)) > rho [1] 0.00860806 > cor(h,g) [1] 0.00860806