Skip to main content

Least Correlated Forex Currency Pairs

Minimizing risk trough Un-correlation

The number of possible major/minor currency is large and trading currencies that are correlated logically increases risk. My Google search for least correlated Forex pairs came up empty so I decided to run the analysis myself.

Using information from this list on Oanda I created a JS script that would loop through the table entires and return the least correlated pairs based on the 1 year value.

Major Currencies

Max correlation between -0.50 and 0.50.

["AUD/JPY", "AUD/USD", "EUR/AUD"]

Major + Minor Currencies

Max correlation between -0.60 and 0.60, with preference to try to keep major currencies in final set

["AUD/CAD", "AUD/CHF", "AUD/HKD", "AUD/JPY", "EUR/GBP", "EUR/SEK", "NZD/CAD", "SGD/CHF", "USD/SAR"]

You may want to run the below snippet and adjust aPAIRS_TO_TRY_FIRST and nMAX_ABSOLUTE_CORRELATION with your own needs. Feel free to comment or follow me @danielsokolows.

Console JS Snippet

document.querySelector('#Table_button').click(); // swithc to table mode which shows numbers
//var aPAIRS_TO_TRY_FIRST = []; // use this to specify which pairs should be compared first and so this should leave them in final set, HOWEVER later pairs can be stilled pruned by previous pairs specified here
// var aPAIRS_TO_TRY_FIRST = ["AUD/JPY", "AUD/USD", "EUR/AUD", "EUR/CHF", "EUR/GBP", "EUR/JPY", "EUR/USD", "GBP/CHF", "GBP/JPY", "GBP/USD", "NZD/USD", "USD/CAD", "USD/CHF", "USD/JPY"]; // major pairs, useful when running this with  
var aPAIRS_TO_TRY_FIRST = ["USD/CAD", "EUR/CAD", "GBP/CAD", "AUD/CAD", "NZD/CAD", "CAD/JPY", "CAD/CHF"]; 
var nMAX_ABSOLUTE_CORRELATION = 0.60;

// program variables
var aPairElementList = Array.prototype.slice.call(document.querySelector('#Table').querySelectorAll('.currency_pair'),0);
var aReturnedPairs = aPairElementList.map(function(oElement) {return oElement.innerText}); // whatever remains in this array is our uncorrelated pairs
var aPairsCompared = [];

// order our clicking pattern based on our pairs to try first
aPAIRS_TO_TRY_FIRST.reverse();
function fReorderInPlacePairElementList (aPairElementList) {
    for (var i = 0; i < aPAIRS_TO_TRY_FIRST.length; i++) {
        for (var j = 0; j < aPairElementList.length; j++) {
            if (aPAIRS_TO_TRY_FIRST[i] == aPairElementList[j].innerText) {
                 var oRemoved = aPairElementList.splice(j,1)[0];
                 aPairElementList.unshift(oRemoved);
            }
        }
    }
    return aPairElementList;
}
fReorderInPlacePairElementList(aPairElementList);


// for each pair select it
for (var i = 0; i < aPairElementList.length; i++) {
    aPairElementList[i].querySelector('button').click();
    // NEED TO RESCAN THE aPairElementList as the nodes have been destroyed and re-created so our aPairElementList is outdated
    aPairElementList = Array.prototype.slice.call(document.querySelector('#Table').querySelectorAll('.currency_pair'),0);
    fReorderInPlacePairElementList(aPairElementList); // and so we also need to re-order here
    
    // now loop over the entire list and prune any correlated pairs from our aReturnedPairs
    for (var j = 0; j < aPairElementList.length; j++) {
        // go to the nth sibling and check for corelation, and remove from our returned list if correlated
        // 7th  next sibling is 1 Year
        if (aPairElementList[i].innerText != aPairElementList[j].innerText && aPairsCompared.indexOf(aPairElementList[i].innerText + aPairElementList[j].innerText) == -1) {
            var nCorelationValue = Number(aPairElementList[j].nextElementSibling.nextElementSibling.nextElementSibling.nextElementSibling.nextElementSibling.nextElementSibling.nextElementSibling.innerText);
            //console.assert(nCorelationValue != NaN, 'Must never have failed to parse correlation');
            if (nCorelationValue == NaN) {throw new Exception('Must never have failed to parse correlation')};
            if (Math.abs(nCorelationValue) > nMAX_ABSOLUTE_CORRELATION ) {
               if (aPAIRS_TO_TRY_FIRST.indexOf(aPairElementList[j].innerText) > -1) {
                console.warn('Warning `' + aPairElementList[j].innerText + '` is in `aPAIRS_TO_TRY_FIRST` but will be removed due to correlation with `' + aPairElementList[i].innerText + '` which is also in `aPAIRS_TO_TRY_FIRST`.');
               }
               console.info('Removing `' + aPairElementList[j].innerText + '` because of correlation with `' + aPairElementList[i].innerText + '` of ' + nCorelationValue);
               if (aReturnedPairs.indexOf(aPairElementList[j].innerText) > -1) {
                aReturnedPairs.splice(aReturnedPairs.indexOf(aPairElementList[j].innerText), 1);
               }
               // store the reverse of the pair so we don't don't compare it and remove it
               aPairsCompared.push(aPairElementList[j].innerText + aPairElementList[i].innerText);
            }
        }
    }
}
console.log(aReturnedPairs)

Comments

Popular posts from this blog

Storing passwords in PuTTY

How to save SSH username/password for auto login in PuTTy The answer is you can't do it...at least in plain PuTTy. However there is an awesome fork with that let's you store the username and password and other additional features called KiTTy . So grab yourself a copy and +1 this if you do, thanks.

Softeher 'Error occurred. (Error code: 2)' sollution

Protocol error occurred. Error was returned from the destination server. The Softether server by default to run on port 443 , if you server also hosts normal https then 443 is already taken and so Softether can't bind to it. When you run `vpncmd` it attempts to connect, find an active port, but of course fails with 'Protocol error occurred. Error was returned from the destination server.' because it's not actually connecting to the vpn server. By default Softether also listens on 992 , 1194 , and 5555 so the sollution is to modify specify `localhost:5555` when executing the `vpncmnd`. If this has helped you feel free to comment or follow me on twitter @danielsokolows .

LightScribe Template Labeler for Windows 10

LightScribe Template Labeler installation "Operating System Inadequate" Issue Unfortunately 'LightScribe Template Labeler' installation will not work on Windows 8 and Windows 10 machines as the install simply will error out with 'Operating System Inadequate'. Trying to install using compatibility mode did not help. Installing LightScribe Template Labeler Workaround However if you simply copy the installed folder from an older machine like Windows 7 into your `C:\\Program Files (x86)\LightScribe Template Labeler`, create a shortcut, then the software will still happily work, see: http://answers.microsoft.com/en-us/windows/forum/windows8_1-performance/lightscribe-templatesimple-labeler-the-system-is/c2ebee28-bfb5-4aef-beb3-a43329561da8?db=5&auth=1 So you can install Windows 7 machine in a virtual machine, install 'LightScribe Template Labeler', and then copy the resulting folder to your Windows 8 or Windows 10 machine. For my own convenien...