// Combined /fileadmin/jslib/fxconsulting/tools/utilities.js
var Utilities={getURLParameters:function(){var a={};if(top.location.search.length>0){var c;var e=unescape(top.location.search.substr(1)).split("&");for(c=0;c<e.length;c++){var b=e[c].split("=")[0];var d=e[c].split("=")[1];if(!d){d=null}else{if(!isNaN(d)){d=parseFloat(d)}}if(!a[b]){a[b]=d}else{if(typeof(a[b])=="object"){a[b].push(d)}else{a[b]=[a[b],d]}}}}return a},getDaysInMonth:function(b,a){if(b<0){b+=12}return[31,((!(a%4)&&((a%100)||!(a%400)))?29:28),31,30,31,30,31,31,30,31,30,31][b]},getFormattedDate:function(b){var a=b.getDate()<10?"0"+b.getDate():b.getDate();var c=b.getMonth()<9?"0"+(b.getMonth()+1):(b.getMonth()+1);return a+"/"+c+"/"+b.getFullYear()},fireCustomEvent:function(c,b){var d=$(c);var a;if(typeof(document.createEventObject)!="undefined"){a=document.createEventObject();a.type=b;d.fireEvent("on"+b,a)}else{a=document.createEvent("Events");a.initEvent(b,true,true);d.dispatchEvent(a)}}};var Calendar=Class.create({parent:null,container:null,tbody:null,date:new Date(),months:["January","February","March","April","May","June","July","August","September","October","November","December"],initialize:function(b,a){this.parent=b;this.container=new Element("div",{"class":"calendarContainer"});this.container.style.top=b.cumulativeOffset()[1]+b.getHeight()+"px";this.container.style.left=b.cumulativeOffset()[0]+"px";if(b.value.strip()&&b.value.match(a)){var c=b.value.split("/");this.date=new Date(c[2],parseFloat(c[1])-1,parseFloat(c[0]))}this.generateCalendar();b.parentNode.appendChild(this.container);b.observe("keydown",this.checkHide.bind(this));b.observe("change",this.hide.bind(this));this.bl=this.hide.bindAsEventListener(this);Event.observe(document,"click",this.bl)},checkHide:function(a){if(a.type=="keydown"&&(a.keyCode==27||a.keyCode==9)){setTimeout(this.hide.bind(this),1)}},hide:function(){if(arguments.length>0){if(arguments[0].type=="click"&&arguments[0].target==this.parent){return}}this.parent.calendar=null;if(this.container.ancestors().size()>0){this.parent.parentNode.removeChild(this.container)}Event.stopObserving(document,"click",this.bl);this.bl=null},generateCalendar:function(){this.container.descendants().invoke("remove");this.generateHeader();var d=new Date(this.date.getFullYear(),this.date.getMonth(),1);var a=new Element("tbody");var c=new Element("tr",{"class":"calendarWeekHeading"}).insert(new Element("td").insert("S")).insert(new Element("td").insert("M")).insert(new Element("td").insert("T")).insert(new Element("td").insert("W")).insert(new Element("td").insert("T")).insert(new Element("td").insert("F")).insert(new Element("td").insert("S"));a.insert(c);var b;for(b=1;b<=this.daysInMonth();b++){d.setDate(b);if(!d.getDay()||b==1){a.insert(this.generateWeek(d))}}this.container.insert(new Element("table",{"class":"calendarTable"}).insert(a))},generateHeader:function(){this.container.insert(this.generateNavButton("&laquo; ",new Date(this.date.getFullYear()-1,this.date.getMonth(),this.date.getDate()))).insert(this.generateNavButton("&lt; ",new Date(this.date.getFullYear(),this.date.getMonth()-1,this.date.getDate()))).insert((new Element("div",{"class":"calendarMonthDisplay"}).insert(this.months[this.date.getMonth()]+"<br />"+this.date.getFullYear()))).insert(this.generateNavButton(" &gt;",new Date(this.date.getFullYear(),this.date.getMonth()+1,this.date.getDate()))).insert(this.generateNavButton(" &raquo;",new Date(this.date.getFullYear()+1,this.date.getMonth(),this.date.getDate())))},generateNavButton:function(c,b){var a=new Element("div",{"class":"calendarNavButton"});a.insert(c);a.observe("mousedown",function(){this.date=b;this.generateCalendar()}.bind(this));return a},generateWeek:function(d){var b=new Element("tr");var a;var c;for(c=d.getDay();c>0;c--){a=this.generateDay(new Date(d.getFullYear(),d.getMonth(),d.getDate()-c)).addClassName("calendarPrevMonth");b.insert(a)}for(c=0;c<=6-d.getDay();c++){a=this.generateDay(new Date(d.getFullYear(),d.getMonth(),d.getDate()+c));if(d.getDate()+c>this.daysInMonth(d.getMonth(),d.getFullYear())){a.addClassName("calendarNextMonth")}b.insert(a)}return b},generateDay:function(b){var a=new Element("td");if(this.date.getFullYear()==b.getFullYear()&&this.date.getMonth()==b.getMonth()&&this.date.getDate()==b.getDate()){a.addClassName("calendarCurrentDay")}if(b.getDay()===0||b.getDay()===6){a.addClassName("calendarWeekend")}else{a.addClassName("calendarDay")}a.innerHTML=b.getDate();a.observe("mousedown",this.setDate.bind(this,b));return a},setDate:function(a){this.date=a;this.parent.value=Utilities.getFormattedDate(a);this.hide();setTimeout(Utilities.fireCustomEvent.bind(Utilities,this.parent,"change"),1)},daysInMonth:function(c,b){var a=this.date.getMonth();var d=this.date.getFullYear();if(arguments.length==2){a=c;d=b}return Utilities.getDaysInMonth(a,d)}});var CalendarManager={showCalendar:function(b,a){if(!b.calendar){b.calendar=new Calendar(b,a)}}};var ErrorHandler={errorTypes:$A([{name:"string",pattern:/^(.+)$/gi,message:"Please fill in the field"},{name:"number",pattern:/^-?[0-9]*\.?[0-9]+$/gi,message:"Please enter a valid number."},{name:"integer",pattern:/^-?[0-9]+$/gi,message:"Please enter a valid integer."},{name:"alphanumeric",pattern:/^[0-9A-Z_\-]+$/ig,message:"Please enter a valid alphanumeric string."},{name:"email",pattern:/^[A-Z0-9._%+\-]+@[A-Z0-9.\-]+\.[A-Z]{2,4}$/i,message:"Please enter a valid email address."},{name:"positiveNumber",pattern:/^[0-9]*\.?[0-9]+$/i,message:"Please enter a positive number."},{name:"date",pattern:/^(0[1-9]|[12][0-9]|3[012])\/(0[1-9]|1[012])\/\d{4}$/i,message:"Please enter a valid date in DD/MM/YYYY format"}]),initialize:function(){this.addErrorHandlers()},addErrorHandlers:function(){this.errorTypes.each(function(a){$$("."+a.name).each(function(b){if(b.hasClassName("date")){b.observe("focus",CalendarManager.showCalendar.bind(window,b,a.pattern))}b.observe("blur",this.dispatchError.bind(this,b,a.pattern,a.message));this.attachFormListener(b)},this)},this)},dispatchError:function(a,d,c,b){if(!(!a.value.strip()&&a.hasClassName("optional"))&&!a.value.match(d)){this.displayError(a,c);return true}else{this.removeErrorMessage(a);return false}},displayError:function(c,d){var b=0.1;if(!c.errorConfig){var a=new Element("div",{style:"background-color:#FF6347;padding:3px;color:#000000;font-size:12px;position:absolute;z-index:9999;text-align:left;left:"+c.cumulativeOffset()[0]+"px;top:"+(c.cumulativeOffset()[1]+c.getHeight())+"px;"}).insert(d);a.setOpacity(b);if(typeof document.body.style.maxHeight=="undefined"){a.setStyle({width:"200px"})}c.errorConfig={messageNode:a,bgcolor:c.getStyle("backgroundColor"),animation:false};c.setStyle({backgroundColor:"#FF6347"});if(c.errorConfig.bgcolor=="transparent"||c.errorConfig.bgcolor=="rgb(255, 255, 255)"){c.errorConfig.bgcolor="#FFFFFF"}if(c.nextSibling){c.parentNode.insertBefore(a,c.nextSibling)}else{c.parentNode.appendChild(a)}this.animateErrorMessage(c,b,0.02);c.observe("mouseover",function(e){if(e.errorConfig){this.animateErrorMessage(e,b,0.02)}}.bind(this,c))}},removeErrorMessage:function(a){if(a.errorConfig){a.setStyle({backgroundColor:a.errorConfig.bgcolor});a.parentNode.removeChild(a.errorConfig.messageNode);a.errorConfig=null}},animateErrorMessage:function(d,c,a,b){if(d.errorConfig){d.errorConfig.messageNode.setStyle({top:(d.cumulativeOffset()[1]+d.getHeight())+"px",left:(d.cumulativeOffset()[0])+"px"});if(c<0){d.errorConfig.animation=false}else{if(c>1){setTimeout(this.animateErrorMessage.bind(this,d,c-a,-0.01,true),1000)}else{if(!d.errorConfig.animation||b){d.errorConfig.animation=true;d.errorConfig.messageNode.setOpacity(c);setTimeout(this.animateErrorMessage.bind(this,d,c+a,a,true),10)}}}}},errorsPresent:function(){var a=false;this.errorTypes.each(function(b){$$("."+b.name).each(function(c){if(this.dispatchError(c,b.pattern,b.message)){a=true}},this)},this);return a},attachFormListener:function(a){if(!a.parentNode){return false}else{if(a.parentNode.nodeName.toLowerCase()=="form"){$(a.parentNode.id).observe("submit",function(b){if(this.errorsPresent()){b.preventDefault()}}.bind(this))}else{this.attachFormListener(a.parentNode)}}}};Event.observe(window,"load",ErrorHandler.initialize.bind(ErrorHandler));var UI={createDropDown:function(c,d,b){var a=new Element("select",{id:d,name:d});c.each(function(f){var e={value:f.code};if(b.toLowerCase()==f.code.toLowerCase()){e.selected="selected"}a.insert(new Element("option",e).update(f.code+" - "+f.name))});return a},addRolloverImages:function(){$$("img.TwoStateRollover").each(this.add2StateRollover.bind(this));$$("img.ThreeStateRollover").each(this.add3StateRollover.bind(this))},add2StateRollover:function(a){a.originalSource=a.src.match(/_((selected)|(up))\./gi);new Element("img",{src:a.src.replace(a.originalSource,"_over.")});a.observe("mouseover",function(b){b.target.src=b.target.src.replace(a.originalSource,"_over.")});a.observe("mouseout",function(b){b.target.src=b.target.src.replace(/_((over)|(down))\./gi,a.originalSource)});return a},add3StateRollover:function(a){this.add2StateRollover(a);new Element("img",{src:a.src.replace(a.originalSource,"_down.")});a.observe("mousedown",function(b){b.target.src=b.target.src.replace("_over.","_down.")});a.observe("mouseup",function(b){b.target.src=b.target.src.replace("_down.","_over.")});return a}};Event.observe(window,"load",UI.addRolloverImages.bind(UI));
// Combined /fileadmin/jslib/fxconsulting/tools/CurrencyBase.js
var Currency=Class.create({amount:0,initialize:function(c,b,a,d){this.isoCode=c;this.name=b||c;this.lendRate=parseFloat(a||1);this.borrowRate=parseFloat(d||1)}});var CurrencyPair=Class.create({base:null,quote:null,sellRate:null,buyRate:null,direction:null,inverted:false,composition:[],initialize:function(d,a,b){this.base=d;this.quote=a;b=b||{};for(var c in b){this[c]=b[c]}},getSellRate:function(){return this.getCurrencyRate("sellRate")},getBuyRate:function(){return this.getCurrencyRate("buyRate")},getCurrencyRate:function(a){if(!this.composition.length){return this[a]}else{return this.composition.invoke("getCurrencyRate",a).inject(1,function(b,c){return b*c})}},getLendRate:function(){return this.getInterestRate("lendRate")},getBorrowRate:function(){return this.getInterestRate("borrowRate")},getInterestRate:function(c,b){if(this.direction!==null){if(!this.composition.length){var a;if(this.direction=="LONG"&&c=="lendRate"){a={currency:this.base,rate:this.base.lendRate}}else{if(this.direction=="SHORT"&&c=="lendRate"){a={currency:this.quote,rate:this.quote.lendRate}}else{if(this.direction=="LONG"&&c=="borrowRate"){a={currency:this.quote,rate:this.quote.borrowRate}}else{if(this.direction=="SHORT"&&c=="borrowRate"){a={currency:this.base,rate:this.base.borrowRate}}}}}if(b=="composition"){return a}else{return[a]}}else{return this.composition.invoke("getInterestRate",c,"composition")}}else{throw"Pair Direction is null - cannot retrive interest rates"}},setDirection:function(a){var b=a.toUpperCase();if(b!="LONG"&&b!="SHORT"){throw"Invalid Direction"}this.direction=b;this.composition.invoke("setDirection",b);return this},setAmount:function(d,f,e){var c=d.toUpperCase();var a=Math.abs(f);if(!this.direction){throw"cannot set amount without setting direction"}if(c==this.base.isoCode&&this.direction=="LONG"){this.base.amount=a;this.quote.amount=a*this.getBuyRate()}else{if(c==this.base.isoCode&&this.direction=="SHORT"){this.base.amount=a;this.quote.amount=a*this.getSellRate()}else{if(c==this.quote.isoCode&&this.direction=="SHORT"){this.quote.amount=a;this.base.amount=a/this.getSellRate()}else{if(c==this.quote.isoCode&&this.direction=="LONG"){this.quote.amount=a;this.base.amount=a/this.getBuyRate()}else{throw"Invalid currency code or amount"}}}}var b={currency:this.base.isoCode,amount:this.base.amount};this.composition.each(function(g){b=g.setAmount(b.currency,b.amount,"composition")},this);if(e=="composition"){return{currency:this.quote.isoCode,amount:this.quote.amount}}else{return this}},convert:function(a,b){this.setAmount(a,b);if(a==this.base.isoCode){return this.quote.amount}else{return this.base.amount}},getUnits:function(){return Math.floor(this.base.amount)},getSpread:function(){return Math.abs(this.getBuyRate()-this.getSellRate())},getFXTradePairs:function(b){if(!this.composition.length){var a=Object.clone(this);if(this.inverted){a.reverse()}if(b=="composition"){return a}else{return[a]}}else{return this.composition.invoke("getFXTradePairs","composition")}},reverse:function(){if(this.direction&&this.direction=="LONG"){this.direction="SHORT"}else{if(this.direction&&this.direction=="SHORT"){this.direction="LONG"}}this.inverted=this.inverted?null:true;var b=this.base;this.base=this.quote;this.quote=b;if(!this.composition.length){var a=this.buyRate;this.buyRate=1/this.sellRate;this.sellRate=1/a}else{this.composition.reverse().invoke("reverse")}return this},toString:function(){var a=this.base.isoCode+"/"+this.quote.isoCode+" at "+this.getSellRate()+"/"+this.getBuyRate();if(this.direction){a+=" "+this.direction}if(this.base.amount){a+="   "+this.base.amount+"/"+this.quote.amount}return a},getName:function(){return this.base.isoCode+"/"+this.quote.isoCode}});var PairFactory=Class.create({currencies:null,initialize:function(a){if(typeof(a)=="function"){this.getNewData(a)}else{this.rawData=a;this.loadData()}},getNewData:function(b,a){this.dataHandler=a;new Ajax.Request(b,{method:"GET",onComplete:this.receiveData.bind(this),onFailure:function(){throw"Server Error"}})},receiveData:function(a){this.rawData=a.responseText.evalJSON();return this.dataHandler(this)},loadData:function(){var b;this.currencies=new Hash();if(!this.rawData.currencies){var a=[];for(b=0;b<this.rawData.pairs.length;b++){a.push(this.rawData.pairs[b].split("/")[0]);a.push(this.rawData.pairs[b].split("/")[1])}this.rawData.currencies=a.uniq().map(function(d){return{isoCode:d}})}if(!this.rawData.selectPairs){this.rawData.selectPairs=this.rawData.pairs}for(b=0;b<this.rawData.currencies.length;b++){var c=this.rawData.currencies[b];this.currencies.set(c.isoCode,new Currency(c.isoCode,c.name,c.lendRate,c.borrowRate))}},createPair:function(){var f,b;if(arguments.length==1){f=arguments[0].split("/")[0].toUpperCase();b=arguments[0].split("/")[1].toUpperCase()}else{if(arguments.length==2){f=arguments[0];b=arguments[1]}else{throw"Invalid currency pair specified"}}var g=f+"/"+b;var a=b+"/"+f;for(var d=0;d<this.rawData.selectPairs.length;d++){var c,h,e;if(f==b){return new CurrencyPair(Object.clone(this.currencies.get(f)),Object.clone(this.currencies.get(b)),{buyRate:1,sellRate:1})}else{if(g==this.rawData.selectPairs[d]){c=$A(this.rawData.pairs).indexOf(g);h=this.rawData.bidRates[c];e=this.rawData.askRates[c];return new CurrencyPair(Object.clone(this.currencies.get(f)),Object.clone(this.currencies.get(b)),{buyRate:e,sellRate:h})}else{if(a==this.rawData.selectPairs[d]){c=$A(this.rawData.pairs).indexOf(a);h=this.rawData.bidRates[c];e=this.rawData.askRates[c];return new CurrencyPair(Object.clone(this.currencies.get(f)),Object.clone(this.currencies.get(b)),{buyRate:(1/h),sellRate:(1/e),inverted:true})}}}}return new CurrencyPair(Object.clone(this.currencies.get(f)),Object.clone(this.currencies.get(b)),{buyRate:0,sellRate:0,composition:this.generateComposition(f,b)})},generateComposition:function(b,a){var c=function(e,d){if($A(this.rawData.selectPairs).indexOf(d+"/"+e)!=-1||$A(this.rawData.selectPairs).indexOf(e+"/"+d)!=-1){return true}else{return false}}.bind(this);if(c(b,"USD")&&c(a,"USD")){return[this.createPair(b+"/USD"),this.createPair("USD/"+a)]}else{if(c(b,"EUR")&&c(a,"EUR")){return[this.createPair(b+"/EUR"),this.createPair("EUR/"+a)]}else{if(c(b,"EUR")&&c(a,"USD")){return[this.createPair(b+"/EUR"),this.createPair("EUR/USD"),this.createPair("USD/"+a)]}else{if(c(b,"USD")&&c(a,"EUR")){return[this.createPair(b+"/USD"),this.createPair("USD/EUR"),this.createPair("EUR/"+a)]}else{throw"invalid composition!"}}}}},getCurrencyCodes:function(){var a=[];this.currencies.each(function(b){a.push({code:b.value.isoCode,name:b.value.name})},this);return a}});
// Combined /fileadmin/jslib/fxconsulting/tools/HedgeCostCalculator.js
var currencyData=new PairFactory(rawCurrencyData);var Field=Class.create({value:null,listeners:[],initialize:function(b,a){this.value=b;this.listeners=[];this.options=a||{}},setValue:function(a){this.value=a;this.listeners.invoke("calculateValue")},getDisplayValue:function(){if(typeof(this.value)=="string"){return this.value}if(!isFinite(this.value)){return""}var e=this.value;var b=2;if(!isNaN(this.options.round)){b=this.options.round}if(this.options.abs){e=Math.abs(e)}if(this.options.percent){e=e*100}e=Math.round(e*Math.pow(10,b))/Math.pow(10,b);var c=e.toString().indexOf(".");if(c!=-1){var a=b-e.toString().substr(c+1).length;e=e.toString();for(var d=0;d<a;d++){e=e.concat("0")}}else{e=e.toString()+".00"}if(this.value<0){e=("("+e.toString().replace(/-/gi,"").replace(/\B(?=(...)*\.)/gi,",")+")").fontcolor("red");if(!b){e=e.replace(/(.*)(\.[0-9]+)(\).*)?/gi,function(){return arguments[1]+arguments[3]})}}else{e=e.toString().replace(/\B(?=(...)*\.)/gi,",");if(!b){e=e.substring(0,e.indexOf("."))}}if(this.options.interest||this.options.percent){e+="%"}return e},listen:function(a){this.listeners.push(a)},addListeners:function(){}});var CalculationField=Class.create(Field,{formula:null,options:null,dependers:null,hc:null,initialize:function($super,c,b,a){$super(0,a);this.formula=c;this.dependers=$A(this.formula.replace(/[+-\/()*]/gi," ").replace(/[0-9]+.?[0-9]+/gi," ").replace(/[\s]+/gi," ").strip().split(" "));this.hc=b},calculateValue:function(){var expression=this.formula;this.dependers.each(function(field){expression=expression.replace(eval("/"+field+"/gi"),function(){return"("+this.hc.fields.get(field).value+")"}.bind(this))},this);if(this.options.abs){this.setValue(Math.abs(eval(expression)))}else{this.setValue(eval(expression))}},addListeners:function(){this.calculateValue();this.hc.fields.each(function(a){if(this.dependers.indexOf(a.key)!=-1){a.value.listen(this)}},this)}});var HedgeCalculator=Class.create({interestRisks:$H({"0":0.001,"31":0.0015,"61":0.0025,"91":0.0035,"121":0.005,"151":0.0075,"181":0.0105,"271":0.014,"366":0.0175}),fields:null,currencyPair:null,hedgePair:null,reportingCurrency:null,foreignCurrency:null,dataSource:null,initialize:function(e,g,a,c,f,b){this.dataSource=e;this.reportingCurrency=g;this.foreignCurrency=a;this.balance=c;this.days=f;this.currencyPair=this.dataSource.createPair(g,a);this.currencyPair.setDirection("LONG");this.currencyPair.setAmount(a,c);this.hedgePair=this.dataSource.createPair(a,g);this.hedgePair.setDirection("SHORT");this.hedgePair.setAmount(a,c);this.days=f;var d=b||{};this.volatility=d.volatility||0.0675;this.quotedForwardRate=d.forwardRate||1;this.balance=c;this.initFields();this.refreshGlobalFields();this.fields.values().invoke("addListeners");this.recalculate();return this},initFields:function(){this.fields=$H({todaysRate:new CalculationField("foreignAmount/reportingAmount",this,{abs:true,round:5}),totalCarryCost:new CalculationField("interestCost+homeHedgeCost",this),totalCost:new CalculationField("interestCost+homeHedgeCost+reportingAmount",this),estimatedCarryForwardRate:new CalculationField("balance/totalCost",this,{round:5}),estimatedForwardCosts:new CalculationField("interestCost+homeHedgeCost+estimatedForwardProfit+interestRiskCost",this),estimatedForwardTotalCost:new CalculationField("reportingAmount+(interestCost+homeHedgeCost+estimatedForwardProfit+interestRiskCost)",this),estimatedForwardRate:new CalculationField("balance/(totalCost+estimatedForwardProfit+interestRiskCost)",this,{round:5}),estimatedForwardRelativeCost:new CalculationField("estimatedForwardTotalCost-totalCost",this),estimatedForwardInterestChange:new CalculationField("(estimatedForwardRelativeCost*365)/(days*reportingAmount)",this,{abs:true,percent:true}),quotedForwardRateTotalCost:new CalculationField("balance/quotedForwardRate",this),quotedForwardRateProfit:new CalculationField("quotedForwardRateTotalCost-(interestCost+homeHedgeCost+reportingAmount+interestRiskCost)",this),quotedForwardRateRelativeCost:new CalculationField("quotedForwardRateTotalCost-totalCost",this),quotedForwardRateCosts:new CalculationField("interestCost+homeHedgeCost+quotedForwardRateProfit+interestRiskCost",this),quotedForwardInterestChange:new CalculationField("(quotedForwardRateRelativeCost*365)/(days*reportingAmount)",this,{abs:true,percent:true}),amountAtRisk:new CalculationField("reportingAmount*volatility",this,{abs:true}),potentialLoss:new CalculationField("(0-1)*(amountAtRisk+totalCarryCost)",this)})},updateInputs:function(a,b){this.balance=a.balance||this.balance;this.days=a.days||this.days;this.volatility=a.volatility||this.volatility;this.quotedForwardRate=a.quotedForwardRate||this.quotedForwardRate;this.reportingCurrency=a.reportingCurrency||this.reportingCurrency;this.foreignCurrency=a.foreignCurrency||this.foreignCurrency;this.recalculate(b)},recalculate:function(a){if(this.currencyPair.base.isoCode!=this.reportingCurrency||this.currencyPair.quote.isoCode!=this.foreignCurrency||a){this.currencyPair=this.dataSource.createPair(this.reportingCurrency,this.foreignCurrency);this.hedgePair=this.dataSource.createPair(this.foreignCurrency,this.reportingCurrency)}if(this.balance>0){this.currencyPair.setDirection("SHORT");this.hedgePair.setDirection("SHORT")}else{this.currencyPair.setDirection("LONG");this.hedgePair.setDirection("LONG")}this.hedgePair.setAmount(this.foreignCurrency,Math.abs(parseInt(this.balance,10)));this.currencyPair.setAmount(this.foreignCurrency,Math.abs(parseInt(this.balance,10)));this.refreshGlobalFields()},setGlobalField:function(c,a,b){if(this.fields.get(c)){this.fields.get(c).setValue(a)}else{this.fields.set(c,new Field(a,b))}},refreshGlobalFields:function(){this.setGlobalField("foreignAmount",this.hedgePair.base.amount*-1*this.balance/Math.abs(this.balance));this.setGlobalField("reportingAmount",this.hedgePair.quote.amount*this.balance/Math.abs(this.balance));this.setGlobalField("spread",this.currencyPair.getSpread(),{round:5});this.setGlobalField("foreignHedgeCost",Math.abs(this.currencyPair.getSpread()*this.currencyPair.base.amount));this.setGlobalField("homeHedgeCost",-1*Math.abs(this.currencyPair.getSpread()*this.currencyPair.base.amount/this.currencyPair.getSellRate()));this.setGlobalField("interestRiskRate",this.lookupInterestRisk(),{percent:true});this.setGlobalField("interestRiskCost",Math.abs(this.hedgePair.quote.amount*this.lookupInterestRisk()*this.days/365)*-1);this.setGlobalField("interestCost",this.calculateTotalInterest());this.setGlobalField("estimatedForwardProfit",-250);this.setGlobalField("sellRate",this.currencyPair.getSellRate(),{round:5});this.setGlobalField("balance",this.balance);this.setGlobalField("days",this.days,{round:0});this.setGlobalField("quotedForwardRate",this.quotedForwardRate,{round:5});this.setGlobalField("baseCurrency",this.currencyPair.base.isoCode);this.setGlobalField("quoteCurrency",this.currencyPair.quote.isoCode);this.setGlobalField("currencyPair",this.currencyPair.base.isoCode+"/"+this.currencyPair.quote.isoCode);this.setGlobalField("volatility",this.volatility,{percent:true,abs:true})},getInterestBreakdown:function(){var a=[];var b=function(c,h){var d=-1,g=c.borrowRate,f="Interest paid on sold";if(h=="lend"){d=1;g=c.lendRate;f="Interest received on purchased"}var i=this.dataSource.createPair(c.isoCode,this.currencyPair.base.isoCode);var e=[new Field(f),new Field(c.isoCode),new Field(g),new Field(c.amount*d),new Field(c.amount*d*g/100),new Field(i.getSellRate()),new Field(c.amount*d*g*i.getSellRate()/100),new Field((c.amount*d*g*i.getSellRate()*this.days)/(100*365))];return e}.bind(this);a=this.hedgePair.getLendRate().collect(function(c){return b(c.currency,"lend")});a=a.concat(this.hedgePair.getBorrowRate().map(function(c){return b(c.currency,"borrow")}));return a},calculateTotalInterest:function(){var a=this.hedgePair.getLendRate().map(function(c){return this.interestSummer(c.currency,"lend")},this);var b=this.hedgePair.getBorrowRate().map(function(c){return this.interestSummer(c.currency,"borrow")},this);return a.concat(b).inject(0,function(c,d){return c+d})},interestSummer:function(a,d){var b=-1,c=a.borrowRate;if(d=="lend"){b=1;c=a.lendRate}var e=this.dataSource.createPair(a.isoCode,this.currencyPair.base.isoCode);return(a.amount*b*c*e.getSellRate()/100)*((this.days)/365)},lookupInterestRisk:function(){var b=this.interestRisks.keys();for(var a=0;a<b.length;a++){if(this.days<parseInt(b[a],10)){return this.interestRisks.get(b[a-1])}}return this.interestRisks.get(b[b.length-1])},refreshData:function(a){this.dataSource.getNewData("/cgi-bin/tools/CurrencyBaseRates.fpl",function(b){this.dataSource=b;this.recalculate(true);a()}.bind(this))}});var HedgeCalculatorBaseUI={hc:null,updateRates:function(){$("updateButton").value="Refreshing Rates...";$("updateButton").disabled=true;this.hc.refreshData(this.finishUpdateRates.bind(this))},finishUpdateRates:function(){this.renderCalculator();$("updateButton").value="Refresh Rates";$("updateButton").disabled=false},renderCalculator:function(){},renderCalculationFields:function(){this.hc.fields.each(function(a){$$("."+a.key).invoke("update",a.value.getDisplayValue())},this)},renderFXTradesBreakdown:function(a){$(a).update();this.hc.hedgePair.getFXTradePairs().each(function(f){var b=f.direction=="LONG"?(new Field(f.getBuyRate(),{round:5}).getDisplayValue()):"&nbsp;";var c=f.direction=="SHORT"?(new Field(f.getSellRate(),{round:5}).getDisplayValue()):"&nbsp;";var e=f.direction=="LONG"?" (buy)":" (sell)";var d=new Element("tr").insert(new Element("td").insert(f.getName())).insert(new Element("td").insert(f.direction+e)).insert(new Element("td").insert(f.getUnits())).insert(new Element("td").insert(c)).insert(new Element("td").insert(b));$(a).insert(d)},this)},renderRateSummary:function(a){var b=function(g){var d=new Element("tr");var f="Direct Pair";if(g.composition.length>0){f="Synthetic Cross"}else{if(g.inverted){f="Inverted Rate"}}d.insert(new Element("td").insert(g.getName()+" ("+f+")"));var c=g.direction=="LONG"?(new Field(g.getBuyRate(),{round:5}).getDisplayValue()):"&nbsp;";var e=g.direction=="SHORT"?(new Field(g.getSellRate(),{round:5}).getDisplayValue()):"&nbsp;";d.insert(new Element("td").insert(e));d.insert(new Element("td").insert(c));return d};$(a).update("");$(a).insert(b(this.hc.currencyPair));$(a).insert(b(this.hc.currencyPair.reverse()));this.hc.currencyPair.reverse()},renderInterestBreakdown:function(a){$(a).update();this.hc.getInterestBreakdown().each(function(b,d){var c=new Element("tr");b.each(function(e){c.insert(new Element("td").insert(e.getDisplayValue()))},this);$(a).insert(c)},this);$(a).insert(new Element("tr").insert(new Element("td",{colspan:7}).insert("Total")).insert(new Element("td").addClassName("yellow").setStyle({borderLeft:"1px solid #5B818A"}).insert(this.hc.fields.get("interestCost").getDisplayValue())))},infoToggle:function(a,b){if(a.innerHTML.indexOf("Show")!=-1){a.innerHTML="Hide More Info";$(b).setStyle({display:"block"})}else{a.innerHTML="Show More Info";$(b).setStyle({display:"none"})}}};
// Combined /fileadmin/jslib/fxconsulting/tools/ForexExposureCalculator.js
var ExposureCalculatorUI=Class.create({reportingCurrency:null,initialize:function(a,f,b,d,e,c){this.reportingCurrency=f;this.hcc=new HedgeCalculator(currencyData,f,b,d,e,{volatility:c});this.calcId=a;this.inputs={};this.inputs.foreignCurrency=UI.createDropDown(currencyData.getCurrencyCodes(),"foreignCurrency",b).observe("change",this.requestVolatility.bind(this));this.inputs.balance=new Element("input",{type:"text",value:d,"class":"number balanceField"}).observe("change",this.inputChange.bind(this,null));this.inputs.days=new Element("input",{type:"text",value:e,"class":"daysField positiveNumber"}).observe("change",this.requestVolatility.bind(this));$("foreignCurrency_"+this.calcId).insert(this.inputs.foreignCurrency);$("balance_"+this.calcId).insert(this.inputs.balance);$("days_"+this.calcId).insert(this.inputs.days)},requestVolatility:function(){if(!ErrorHandler.errorsPresent()){new Ajax.Request("/cgi-bin/tools/get_volatilities.pl",{method:"GET",parameters:{pair:this.reportingCurrency+"/"+this.inputs.foreignCurrency.value,days:parseFloat(this.inputs.days.value)},onComplete:this.inputChange.bind(this),onFailure:this.serverError})}},updateReportingCurrency:function(a){this.reportingCurrency=a;this.requestVolatility()},serverError:function(){alert("There was a problem communicating with the server. Using average volatility.")},inputChange:function(b){if(!ErrorHandler.errorsPresent()){var a={foreignCurrency:this.inputs.foreignCurrency.value,balance:parseFloat(this.inputs.balance.value),days:parseFloat(this.inputs.days.value),reportingCurrency:this.reportingCurrency};if(b){a.volatility=parseFloat(b.responseText)}this.hcc.updateInputs(a);this.render()}},render:function(){this.hcc.fields.each(function(b){$$("."+this.calcId+" ."+b.key).each(function(c){c.update(b.value.getDisplayValue())},this)},this);if($("moreInfoLinkContainer_"+this.calcId)){var a={reportingCurrency:this.reportingCurrency,foreignCurrency:this.inputs.foreignCurrency.value,balance:this.inputs.balance.value,days:this.inputs.days.value};$("moreInfoLinkContainer_"+this.calcId).update('<a href="/tools/hedging-cost-comparison-tool.shtml?'+Object.toQueryString(a)+'" target="_blank">Get Hedge Cost Breakdown</a>')}}});var ExposureCalculatorUIManager={guid:0,calculators:new Hash(),newInputs:null,dynamicRows:{},callLock:false,initialize:function(){var a=Utilities.getURLParameters();var b=a.reportingCurrency||"USD";this.reportingCurrency=UI.createDropDown(currencyData.getCurrencyCodes(),"reportingCurrency",b);$("reportingCurrencyContainer").insert(this.reportingCurrency);this.reportingCurrency.observe("change",this.refreshExposures.bind(this)).oldSelectedIndex=this.reportingCurrency.selectedIndex;if(a.reportingCurrency){this.newInputs={foreignCurrency:UI.createDropDown(currencyData.getCurrencyCodes(),"newForeignCurrency",a.foreignCurrency),balance:new Element("input",{type:"text",value:a.balance,"class":"balanceField number"}),days:new Element("input",{type:"text",value:a.days,"class":"daysField positiveNumber"}),externalRequest:true};this.addNewCalc()}else{this.addNewCalcRow()}},addNewButtonRow:function(){var a=new Element("input",{type:"button",value:"Add New Row"}).observe("click",this.toggleNewCalcRows.bind(this));this.dynamicRows.buttonRow=new Element("tr").insert(new Element("td",{colspan:9,style:"text-align:left;padding-left:10px;"}).insert(a));$("calculatorsContainer").insert(this.dynamicRows.buttonRow)},addNewCalcRow:function(){this.newInputs={foreignCurrency:UI.createDropDown(currencyData.getCurrencyCodes(),"newForeignCurrency","EUR"),balance:new Element("input",{type:"text","class":"balanceField number"}).observe("change",this.addNewCalc.bind(this)),days:new Element("input",{type:"text","class":"daysField positiveNumber"}).observe("change",this.addNewCalc.bind(this))};this.dynamicRows.newCalcRow=new Element("tr").insert(new Element("td").insert(this.newInputs.foreignCurrency)).insert(new Element("td").insert(this.newInputs.balance)).insert(new Element("td").insert(this.newInputs.days)).insert(new Element("td").insert(UI.add3StateRollover(new Element("img",{src:"/fileadmin/images/fxconsulting/tools/bt_icon_reload_up.gif"})).observe("click",this.addNewCalc.bind(this)))).insert(new Element("td")).insert(new Element("td")).insert(new Element("td")).insert(new Element("td")).insert(new Element("td").insert(UI.add3StateRollover(new Element("img",{src:"/fileadmin/images/fxconsulting/tools/bt_icon_close_up.gif"})).observe("click",this.toggleNewCalcRows.bind(this))));$("calculatorsContainer").insert(this.dynamicRows.newCalcRow);ErrorHandler.addErrorHandlers()},toggleNewCalcRows:function(){if(!this.dynamicRows.buttonRow){this.dynamicRows.newCalcRow.remove();this.dynamicRows.newCalcRow=null;this.addNewButtonRow()}else{this.dynamicRows.buttonRow.remove();this.dynamicRows.buttonRow=null;this.addNewCalcRow()}},addNewCalc:function(){if(this.newInputs.days.value.strip()&&this.newInputs.balance.value.strip()&&!this.callLock){if(!ErrorHandler.errorsPresent()){this.callLock=true;new Ajax.Request("/cgi-bin/tools/get_volatilities.pl",{method:"GET",parameters:{pair:this.reportingCurrency.value+"/"+this.newInputs.foreignCurrency.value,days:this.newInputs.days.value},onComplete:this.addNewExposure.bind(this),onFailure:function(){alert("There was a problem communicating with the server. Using average volatility")}})}}},addNewExposure:function(b){var c=parseFloat(b.responseText);var a=this.getGUID();var d=new Element("tr",{"class":a,id:a});d.insert(new Element("td",{id:"foreignCurrency_"+a}));d.insert(new Element("td",{id:"balance_"+a}));d.insert(new Element("td",{id:"days_"+a}));d.insert(new Element("td").insert(UI.add3StateRollover(new Element("img",{src:"/fileadmin/images/fxconsulting/tools/bt_icon_reload_up.gif"}))));d.insert(new Element("td").insert(UI.add3StateRollover(new Element("img",{src:"/fileadmin/images/fxconsulting/tools/bt_icon_info_up.gif"}))).observe("click",this.popupMoreInfo.bind(this,a)));d.insert(new Element("td",{"class":"amountAtRiskContainer amountAtRisk"}));d.insert(new Element("td",{"class":"totalCarryCostContainer totalCarryCost"}));d.insert(new Element("td",{"class":"potentialLoss"}));d.insert(new Element("td").insert(UI.add3StateRollover(new Element("img",{src:"/fileadmin/images/fxconsulting/tools/bt_icon_close_up.gif"})).observe("click",this.removeCalculator.bind(this,a))));$("calculatorsContainer").insert(d);this.calculators.set(a,new ExposureCalculatorUI(a,this.reportingCurrency.value,this.newInputs.foreignCurrency.value,parseFloat(this.newInputs.balance.value),parseFloat(this.newInputs.days.value),c));this.callLock=false;this.calculators.get(a).render();if(!this.newInputs.externalRequest){this.toggleNewCalcRows()}else{this.addNewButtonRow()}this.newInputs={}},removeCalculator:function(a){$$("."+a).invoke("remove");this.calculators.unset(a)},refreshExposures:function(){if(ErrorHandler.errorsPresent()){this.reportingCurrency.selectedIndex=this.reportingCurrency.oldSelectedIndex;alert("Please fix input errors before selecting new reporting currency")}else{this.reportingCurrency.oldSelectedIndex=this.reportingCurrency.selectedIndex;this.calculators.values().invoke("updateReportingCurrency",this.reportingCurrency.value)}},popupMoreInfo:function(b){if(!this.calculators.get(b).popupRow){var a=$(b);this.calculators.get(b).popupRow=new Element("tr",{"class":"popupRow "+b}).insert(new Element("td",{colspan:9}).insert(this.generatePopupDiv(b)));a.parentNode.insertBefore(this.calculators.get(b).popupRow,a.next());this.calculators.get(b).render()}else{this.calculators.get(b).popupRow.remove();this.calculators.get(b).popupRow=null}},generatePopupDiv:function(h){var g=$$("#"+h+" .amountAtRiskContainer")[0];var f=g.cumulativeOffset()[0]-$$("table.results")[0].cumulativeOffset()[0];var e=g.getWidth()+$$("#"+h+" .totalCarryCostContainer")[0].getWidth();var c=new Element("div",{"class":"popup"}).insert(UI.add3StateRollover(new Element("img",{src:"/fileadmin/images/fxconsulting/tools/bt_icon_close_up.gif"})).observe("click",this.popupMoreInfo.bind(this,h))).setStyle({textAlign:"right",width:e+"px",height:"20px"});var d=new Element("div",{"class":"popup"}).insert(this.riskBreakdown);d.setStyle({width:e+"px"});var a=new Element("div",{"class":"popup"}).setStyle({textAlign:"right",width:e+"px",height:"20px"}).insert('<span id="moreInfoLinkContainer_'+h+'"></span>');var b=new Element("div",{style:"padding-left:"+f+"px;"}).insert(c).insert(d).insert(a);return b},getGUID:function(){return"exc_"+(++this.guid)},riskBreakdown:'<table class="breakdown"><tr><td class="label">Forex Amount</td><td class="balance" style="border-right:1px solid #5B818A;">&nbsp</td> <td class="label">Estimated Spread Cost</td><td class="homeHedgeCost">&nbsp</td></tr><tr class="mathSigns"><td>&nbsp</td><td style="border-right:1px solid #5B818A;text-align:center;">&divide;</td> <td>&nbsp</td><td style="text-align:center;">+</td></tr><tr><td class="label" style="border-bottom:1px solid #5B818A;">Spot Rate</td><td class="sellRate" style="border-right:1px solid #5B818A;border-bottom:1px solid #5B818A;">&nbsp</td><td class="label" style="border-bottom:1px solid #5B818A;">Interest Carry Costs</td><td class="interestCost"  style="border-bottom:1px solid #5B818A;">&nbsp</td></tr><tr><td class="label">Reporting Currency Amount (<span class="baseCurrency"></span>)</td><td class="reportingAmount" style="border-right:1px solid #5B818A;">&nbsp</td><td class="label">Total Estimated Hedging (Cost)/Benefit</td><td class="totalCarryCost">&nbsp</td></tr><tr class="mathSigns"><td>&nbsp</td><td style="border-right:1px solid #5B818A;text-align:center;">x</td> <td>&nbsp</td><td>&nbsp</td></tr><tr><td class="label" style="border-bottom:1px solid #5B818A;">Historical Volatility (%)</td><td class="volatility" style="border-right:1px solid #5B818A;border-bottom:1px solid #5B818A;">&nbsp</td><td></td><td></td></tr><tr><td class="label">Total Amount at Risk</td><td class="amountAtRisk" style="border-right:1px solid #5B818A;">&nbsp</td></tr></table>'};Event.observe(window,"load",ExposureCalculatorUIManager.initialize.bind(ExposureCalculatorUIManager));
