//////////////////////////////////////////////////
// Init
window.onload = function()
{
	if (NCHN > 0)
		UpdateControlPanel();
	LoadAds();
}

function LoadAds()
{
	if (SITE == "DOTCOM")
	{
		var top, left, obj, ad, adwidth;
		var adlist = new Array("AdLeft1");
		var pslist = new Array("posAdLeft1");
		var wdlist = new Array(175,-1);
		for (var i = 0; i < adlist.length; i++)
		{
			top = 0; left = 0;
			obj = document.getElementById(pslist[i]);
			if(obj == null)
			    continue;
			if (obj.offsetParent)
			{
				while (obj = obj.offsetParent)
				{
					top += obj.offsetTop;
					left += obj.offsetLeft;
				}
			}

			ad = document.getElementById(adlist[i]);
			adwidth = ad.offsetWidth;
			ad.style.top = top;
			if (wdlist[i] == 0)
				ad.style.left = left;
			else
				ad.style.left = left + (wdlist[i] - adwidth)/2;
			ad.style.visibility = "visible";
		}
	}
	if (document.cookie.indexOf("OverlayAdOption") < 0)
		ShowOverlayAd();
}

function ShowOverlayAd()
{
	var top = 0; left = 0;
	var obj = document.getElementById("posAdx28");
	if (obj.offsetParent)
	{
		while (obj = obj.offsetParent)
		{
			top += obj.offsetTop;
			left += obj.offsetLeft;
		}
	}
	var ad = document.getElementById("Adx28");
	if (ad == null) return;
	ad.style.top = (top + 25) + 'px';
	ad.style.left = (left + 32) + 'px';
	ad.style.visibility = "visible";
	setTimeout("HideOverlayAd()", 15000);
	document.cookie = "OverlayAdOption";
}

function HideOverlayAd()
{
	var ad = document.getElementById("Adx28");
	ad.style.visibility = "hidden";
}

var winArray = new Array();
window.onunload = function()
{
	for (var i = 0; i < winArray.length; i++)
		winArray[i].close();
	SaveCookie();
};

function SaveCookie()
{
	if (strOptions.length > 0)
	{
		var opview = BuildView();
		var expires = new Date();
		expires.setDate(expires.getDate() + 365);

		var cook= "OptionView=" + opview + "; expires=" + expires.toGMTString() + "; path=/; domain=.morningstar.com";
		document.cookie = cook;
	}
}

function BuildView()
{
	var opview = "3";

	var chkList = "";
	var obj = eval("document.FormChoice." + colName[colOrder[0]]);
	if (obj.checked)
		chkList += colName[colOrder[0]] + ",1";
	else
		chkList += colName[colOrder[0]] + ",0";
	for (var i = 1; i < colOrder.length; i++)
	{
		obj = eval("document.FormChoice." + colName[colOrder[i]]);
		if (obj == null)
			continue;
		if (obj.checked)
			chkList += "|" + colName[colOrder[i]] + ",1";
		else
			chkList += "|" + colName[colOrder[i]] + ",0";
	}
	opview += "~" + chkList;

	var radioBtn = "";
	if (document.FormChoice.RadioEndPoint[1].checked)
		radioBtn = "~1";
	else if (document.FormChoice.RadioEndPoint[2].checked)
		radioBtn = "~2";
	else
		radioBtn = "~0";
	if (document.FormChoice.RadioGreek[1].checked)
		radioBtn += ",1";
	else
		radioBtn += ",0";
	if (document.FormChoice.RadioLayout[0].checked)
		radioBtn += ",0";
	else
		radioBtn += ",1";
	if (document.FormChoice.RadioTable[0].checked)
		radioBtn += ",0";
	else if (document.FormChoice.RadioTable[1].checked)
		radioBtn += ",1";
	else if (document.FormChoice.RadioTable[2].checked)
		radioBtn += ",2";
	else if (document.FormChoice.RadioTable[3].checked)
		radioBtn += ",3";
	else if (document.FormChoice.RadioTable[4].checked)
		radioBtn += ",4";
	if (document.FormChoice.RadioSStep[0].checked)
		radioBtn += ",1";
	else if (document.FormChoice.RadioSStep[1].checked)
		radioBtn += ",2";
	if (document.FormChoice.RadioTStep[0].checked)
		radioBtn += ",1";
	else if (document.FormChoice.RadioTStep[1].checked)
		radioBtn += ",2";
	opview += radioBtn;

	opview += "~" + chnExpireDate.join(",");

	if (document.images["imgShowChoice"].src == "http://im.morningstar.com/im/OptionChain_Show.gif")
		opview += "~hide";
	else
		opview += "~show";

	opview += "~" + document.FormOption.InputCurViewName.value;

	opview += "~";
	if (document.FormChoice.chkCall.checked)
		opview += "chkCall,1|";
	else
		opview += "chkCall,0|";
	if (document.FormChoice.chkPut.checked)
		opview += "chkPut,1";
	else
		opview += "chkPut,0";

	opview += "~";
	if (document.FormChoice.InputMoneyFrom.value.length > 0)
		opview += document.FormChoice.InputMoneyFrom.value + ",";
	else
		opview += ",";
	if (document.FormChoice.InputMoneyTo.value.length > 0)
		opview += document.FormChoice.InputMoneyTo.value + ",";
	else
		opview += ",";

	return opview;
}

//////////////////////////////////////////////////
// Control panel
function ShowChoice()
{
	var obj = document.getElementById("idCanvasChoice");
	if (obj == null)
		return;

	if (document.images["imgShowChoice"].src == "http://im.morningstar.com/im/OptionChain_Show.gif")
	{
		document.images["imgShowChoice"].src = "http://im.morningstar.com/im/OptionChain_Hide.gif";
		obj.style.display = "";
		document.cookie = "showStatusOption=show";
	}
	else
	{
		document.images["imgShowChoice"].src = "http://im.morningstar.com/im/OptionChain_Show.gif";
		obj.style.display = "none";
		document.cookie = "showStatusOption=hide";
	}
}

var bShowHint = false;
function ShowHint(id)
{
	bShowHint = true;
	setTimeout("ShowHint2('" + id + "')", 500);
}

function HideHint()
{
	bShowHint = false;
	var hint = document.getElementById("PopupHint");
	if (hint != null)
		hint.style.visibility = "hidden";

	var hintText = document.getElementById("TextHint");
	if (hintText != null)
		hintText.innerHTML = "";
}

function ShowHint2(id)
{
	if (bShowHint == false)
		return;

	var hintPos, hintID;
	var hints = id.split("|");
	if (hints.length == 1)
	{
		hintPos = hintID = hints[0];
	}
	else
	{
		hintPos = hints[0];
		hintID = hints[1];
	}
	if (hintPos == "" || hintID == "")
		return;

	ajax({
		url: "GetHints.aspx?HintId=" + hintID,
		onSuccess: function(text) {
			if (text.length <= 0)
				return;

			var top = 0, left = 0;
			var obj = document.getElementById(hintPos);
			if (obj == null)
				return;
			if (obj.offsetParent)
			{
				top += obj.offsetTop;
				while (obj = obj.offsetParent)
					top += obj.offsetTop;
			}
			obj = document.getElementById("hintHistVol");
			if (obj == null)
				return;
			if (obj.offsetParent)
			{
				left += obj.offsetLeft;
				while (obj = obj.offsetParent)
					left += obj.offsetLeft;
			}

			var hintText = document.getElementById("TextHint");
			if (hintText != null)
				hintText.innerHTML = text;

			var hint = document.getElementById("PopupHint");
			if (hint != null)
			{
				hint.style.top = top;
				hint.style.left = left;
				hint.style.visibility = "visible";
			}
		}
	});
}

// sjin glossary
function ShowHintB(id)
{
	bShowHint = true;

	var hintPos, hintID;
	var hints = id.split("|");
	if (hints.length == 1)
	{
		hintPos = hintID = hints[0];
	}
	else
	{
		hintPos = hints[0];
		hintID = hints[1];
	}
	if (hintPos == "" || hintID == "")
		return;

	ajax({
		url: "Glossary.aspx?HintId=" + hintID,
		onSuccess: function(text) {
			if (text.length <= 0)
				return;
			alert(text);
			var pos0 = text.indexOf(hintID);
			var pos1 = text.indexOf('<div id="' + hintID + 'Short">', pos0);
			var pos2 = text.indexOf("</div>", pos0);
			pos0 = text.indexOf("<h3>", pos0);
			if (pos1 > 0)
				text = text.substring(pos0, pos1);
			else
				text = text.substring(pos0, pos2);
			if (pos1 > 0)
				text += "Click <img src='http://im.morningstar.com/im/help_icon.gif' width=12 height=15 border=0> for more ...";
			alert(text);

			var top = 0, left = 0;
			var obj = document.getElementById(hintPos);
			if (obj == null)
				return;
			if (obj.offsetParent)
			{
				top += obj.offsetTop;
				while (obj = obj.offsetParent)
					top += obj.offsetTop;
			}
			obj = document.getElementById("hintHistVol");
			if (obj == null)
				return;
			if (obj.offsetParent)
			{
				left += obj.offsetLeft;
				while (obj = obj.offsetParent)
					left += obj.offsetLeft;
			}

			var hintText = document.getElementById("TextHint");
			if (hintText != null)
				hintText.innerHTML = text;

			var hint = document.getElementById("PopupHint");
			if (hint != null)
			{
				hint.style.top = top;
				hint.style.left = left;
				hint.style.visibility = "visible";
			}
		}
	});
}

function GoHelp(c, hint)
{
	var url = "Glossary_" + c + ".htm#" + hint;
	var win = window.open(url, "Glossary","width=760,height=512,scrollbars=yes,resizable=yes");
}

function ChangeView()
{
	var index = document.FormChoice.SelectView.selectedIndex;
	if (index < 0)
		return;
	var view = document.FormChoice.SelectView.options[index].value;
	if (view.length <= 0)
		return;
	document.FormOption.InputCurViewName.value = document.FormChoice.SelectView.options[index].text;
	document.FormOption.InputCurrentView.value = document.FormChoice.SelectView.options[index].value;
	var views = view.split("|");
	var pair = views[views.length-2].split(",");
	if (pair[0] == "chkCall")
	{
		if (pair[1] == "0")
			document.FormChoice.chkCall.checked = false;
		else
			document.FormChoice.chkCall.checked = true;
	}
	pair = views[views.length-1].split(",");
	if (pair[0] == "chkPut")
	{
		if (pair[1] == "0")
			document.FormChoice.chkPut.checked = false;
		else
			document.FormChoice.chkPut.checked = true;
	}
	for (var i = 0; i < views.length-2; i++)
	{
		pair = views[i].split(",");
		for (var j = 0; j < colName.length; j++)
		{
			if (pair[0] == colName[j])
			{
				var obj = eval("document.FormChoice." + colName[j]);
				if (obj == null)
					break;
				if (pair[1] == "0")
				{
					obj.checked = false;
					colStatus[j] = "";
				}
				else
				{
					obj.checked = true;
					colStatus[j] = "checked";
				}
				colOrder[i] = j;
				break;
			}
		}
	}
	if (TableType == 0)
	{
		if (index == 1)
		{
			EndPoint = 0;
			GreeksIn = 1;
			Layout = 0;
			document.FormChoice.RadioEndPoint[0].checked = true;
			document.FormChoice.RadioGreek[1].checked = true;
			document.FormChoice.RadioLayout[0].checked = true;
			UpdateTables(true, false);
		}
		else if (index == 2 || index == 3)
		{
			EndPoint = 2;
			GreeksIn = 1;
			Layout = 0;
			document.FormChoice.RadioEndPoint[2].checked = true;
			document.FormChoice.RadioGreek[1].checked = true;
			document.FormChoice.RadioLayout[0].checked = true;
			UpdateTables(true, false);
		}
		else if (index == 4 || index == 5)
		{
			EndPoint = 1;
			GreeksIn = 1;
			Layout = 0;
			document.FormChoice.RadioEndPoint[1].checked = true;
			document.FormChoice.RadioGreek[1].checked = true;
			document.FormChoice.RadioLayout[0].checked = true;
			UpdateTables(true, false);
		}
		else
		{
			UpdateTables(false, false);
		}
	}
	else
	{
		UpdateTables(false, false);
	}
}

// sjin Update later
function OpenCustView()
{
	if (userType == "")
	{
		var redirUrl = "http://quote.morningstar.com/forbidden/loginraw.html?referid=A2915";
		var vurlpara = "&vurl=http%3a%2f%2fquote.morningstar.com%2fOption%2fOptions.aspx%3fTicker%3d" + Ticker + "%26sLevel%3d" + hasPDF;
		document.location = redirUrl + vurlpara;
		return;
	}

	var chkList = "";
	for (var i = 0; i < colName.length; i++)
	{
		var obj = eval("document.FormChoice." + colName[colOrder[i]]);
		if (obj.checked)
			chkList += colName[colOrder[i]] + ",1|";
		else
			chkList += colName[colOrder[i]] + ",0|";
	}
	if (document.FormChoice.chkCall.checked)
		chkList += "chkCall,1|";
	else
		chkList += "chkCall,0|";
	if (document.FormChoice.chkPut.checked)
		chkList += "chkPut,1";
	else
		chkList += "chkPut,0";
	var win = window.open("OptionView.aspx?column="+chkList, "CustomView","width=451,height=512,scrollbars=yes");
	winArray.push(win);
	win.focus();
}

function RefreshView(name, views)
{
	var index = document.FormChoice.SelectView.selectedIndex;
	var selName = "", selView = "";
	if (index > 0 && index != 6)
	{
		selName = document.FormChoice.SelectView.options[index].text;
		selView = document.FormChoice.SelectView.options[index].value;
	}

	var i = 0, ic = 6;
	var arrName = new Array();
	var arrView = new Array();
	for (i = 0; i < ic; i++)
	{
		arrName[i] = document.FormChoice.SelectView.options[i].text;
		arrView[i] = document.FormChoice.SelectView.options[i].value;
	}

	document.FormChoice.SelectView.options.length = 0;

	for (i = 0; i < ic; i++)
		document.FormChoice.SelectView.options[i] = new Option(arrName[i], arrView[i]);

	if (views.length > 0)
	{
		if (ic == 6)
			document.FormChoice.SelectView.options[ic++] = new Option("----- Custom View(s) -----", "");

		var arrView = views.split("@@@");
		for (i = 0; i < arrView.length-1; i++)
		{
			var pair = arrView[i].split("~");
			document.FormChoice.SelectView.options[i+ic] = new Option(pair[0], pair[1]);
		}
	}

	if (index < ic && name.length <= 0)
	{
		document.FormChoice.SelectView.selectedIndex = index;
		return;
	}

	if (name.length > 0 && name != selName)
	{
		selName = name;
		selView = "";
	}

	var bRefresh = false;
	if (document.FormChoice.SelectView.options.length > ic)
	{
		document.FormChoice.SelectView.selectedIndex = ic;
		bRefresh = true;
		for (i = ic; i < document.FormChoice.SelectView.options.length; i++)
		{
			if (selName == document.FormChoice.SelectView.options[i].text)
			{
				document.FormChoice.SelectView.selectedIndex = i;
				if (selView == document.FormChoice.SelectView.options[i].value)
					bRefresh = false;
				else
					bRefresh = true;
				break;
			}
		}
	}
	else
	{
		document.FormChoice.SelectView.selectedIndex = 1;
		bRefresh = true;
	}
	if (bRefresh == true)
		ChangeView();
}

function UpdateControlPanel()
{
	var obj = document.getElementById("idSStep");
	if (obj == null)
		return;
/*
	if (TableType == 0 || TableType == 1)
	{
		document.FormChoice.RadioGreek[1].disabled = false;
	}
	else
	{
		GreeksIn = 0;
		document.FormChoice.RadioGreek[0].checked = true;
		document.FormChoice.RadioGreek[1].disabled = true;
	}
*/
	if (TableType == 1)
	{
		document.FormChoice.RadioLayout[0].disabled = true;
		document.FormChoice.RadioLayout[1].disabled = true;
	}
	else
	{
		document.FormChoice.RadioLayout[0].disabled = false;
		document.FormChoice.RadioLayout[1].disabled = false;
	}

	if (TableType == 0)
	{
		obj.style.display = "none";
	}
	else if	(TableType == 1)
	{
		obj.style.display = "none";
	}
	else if	(TableType == 2)
	{
		obj.style.display = "";
		document.FormChoice.RadioSStep[0].disabled = false;
		document.FormChoice.RadioSStep[1].disabled = false;
		document.FormChoice.RadioTStep[0].disabled = true;
		document.FormChoice.RadioTStep[1].disabled = true;
	}
	else if	(TableType == 3)
	{
		obj.style.display = "";
		document.FormChoice.RadioSStep[0].disabled = true;
		document.FormChoice.RadioSStep[1].disabled = true;
		document.FormChoice.RadioTStep[0].disabled = false;
		document.FormChoice.RadioTStep[1].disabled = false;
	}
	else if	(TableType == 4)
	{
		obj.style.display = "";
		document.FormChoice.RadioSStep[0].disabled = false;
		document.FormChoice.RadioSStep[1].disabled = false;
		document.FormChoice.RadioTStep[0].disabled = false;
		document.FormChoice.RadioTStep[1].disabled = false;
	}

/* enable saved view for Combo
	obj = document.getElementById("idSaveView");
	if (obj == null)
		return;
	if (TableType == 1)
	{
		document.FormChoice.SelectView.disabled = true;
		obj.innerHTML = "<img src='http://im.morningstar.com/im/OptionChain_SaveView_Off.gif' width=94 height=19 border=0 align=absbottom>";
	}
	else
	{
		document.FormChoice.SelectView.disabled = false;
		obj.innerHTML = "<a href='javascript:OpenCustView()'><img src='http://im.morningstar.com/im/OptionChain_SaveView.gif' width=94 height=19 border=0 align=absbottom></a>";
	}
*/

	for (var i = 0; i < NUMCOL; i++)
	{
		obj = eval("document.FormChoice." + colName[i]);
		if (obj != null)
			obj.disabled = colBlock[i] == "1" ? true : false;
	}
	document.FormChoice.chkCall.disabled = colBlock[NUMCOL] == "1" ? true : false;
	document.FormChoice.chkPut.disabled = colBlock[NUMCOL+1] == "1" ? true : false;
}

// When End Point, Strike/Stock, Greeks, and layout changed.
// bc: if recalculate tables. bv: if recalculate IV.
function UpdateTables(bc, bv)
{
	if (bc == true)
	{
		for (var i = 0; i < NCHN; i++)
		{
			if (GetChain2(i) == -1)
				continue;
			chnTables[i] = CalATable(i, bv);
		}
	}

	for (var i = 0; i < NCHN; i++)
	{
		if (chnExpireDate[i] == "" || GetChain2(i) == -1 || chnOptions[i] == "")
			continue;

		RemoveTable(i);
		WriteTable(i);
	}
	SaveCookie();
}

// When table type and spread spacing changed.
function UpdateChains()
{
	CalTables(true);
	WriteTables();
	SaveCookie();
}

function UpdateEndPoint(ep)
{
	if (EndPoint == ep)
		return;
	EndPoint = ep;
	UpdateTables(true, true);
}

function ChangeMoney()
{
	var from = parseFloat(document.FormChoice.InputMoneyFrom.value);
	var to = parseFloat(document.FormChoice.InputMoneyTo.value);
	if (isNaN(from))
	{
		alert("Please enter a valid Stock/Strike From value");
		document.FormChoice.InputMoneyFrom.value = MoneyFrom;
		return;
	}
	if (isNaN(to))
	{
		alert("Please enter a valid Stock/Strike To value");
		document.FormChoice.InputMoneyTo.value = MoneyTo;
		return;
	}
	if (from >= to)
	{
		alert("Stock/Strike From value is greater than To value. Please enter valid values");
		document.FormChoice.InputMoneyFrom.value = MoneyFrom;
		document.FormChoice.InputMoneyTo.value = MoneyTo;
		return;
	}
	MoneyFrom = from;
	MoneyTo = to;
	UpdateTables(false, false);
}

function UpdateGreeks(gi)
{
	if (GreeksIn == gi)
		return;
	GreeksIn = gi;
	UpdateTables(true, false);
}

function UpdateLayout(lo)
{
	if (Layout == lo)
		return;
	Layout = lo;
	UpdateTables(false, false);
}

function UpdateTableType(tt)
{
	if (TableType == tt)
		return;
	TableType = tt;
	colBlock = ttBlock[TableType].split(",");
	UpdateControlPanel();
	UpdateChains();
}

function UpdateSStep(ss)
{
	if (StrikeStep == ss)
		return;
	StrikeStep = ss;
	UpdateTables(true, true);
}

function UpdateTStep(ts)
{
	if (TimeStep == ts)
		return;
	TimeStep = ts;
	UpdateChains();
}

//////////////////////////////////////////////////
// Chain header
function ShowTable(id)
{
	var obj = document.getElementById("idExpand"+id);
	if (obj == null)
		return;
	var text = obj.innerHTML;
	if (text == "Click to Hide")
	{
		obj.innerHTML = "Click to Expand";
		chnExpireDate[id] = "";
		RemoveChain(id);
	}
	else
	{
		obj.innerHTML = "Click to Hide";
		chnExpireDate[id] = chnExpireDateShort[id];
		if (chnTables[id] == "")
			chnTables[id] = CalATable(id, true);
		WriteChain(id);
	}

	var showAll = "Hide All";
	for (var i = 0; i < NCHN; i++)
	{
		if (GetChain2(i) == -1)
			continue;

		if (chnExpireDate[i] == "")
		{
			showAll = "Show All";
			break;
		}
	}

	for (var i = 0; i < NCHN; i++)
	{
		if (GetChain2(i) == -1)
			continue;

		obj = document.getElementById("idShowAll" + i);
		if (obj != null)
			obj.innerHTML = showAll;
	}

	SaveCookie();
}

function ShowAll(id)
{
	var objShowAll = document.getElementById("idShowAll" + id);
	if (objShowAll == null)
		return;
	var text = objShowAll.innerHTML;
	for (var i = 0; i < NCHN; i++)
	{
		if (GetChain2(i) == -1)
			continue;

		objShowAll = document.getElementById("idShowAll" + i);
		var objExpand = document.getElementById("idExpand" + i);
		if (objShowAll == null || objExpand == null)
			continue;
		if (text == "Show All")
		{
			objShowAll.innerHTML = "Hide All";
			objExpand.innerHTML = "Click to Hide";
			if (chnExpireDate[i] == "")
			{
				chnExpireDate[i] = chnExpireDateShort[i];
				if (chnTables[i] == "")
					chnTables[i] = CalATable(i, true);
				WriteChain(i);
			}
		}
		else
		{
			objShowAll.innerHTML = "Show All";
			if (i == id)
				continue;

			if (chnExpireDate[i] != "")
			{
				chnExpireDate[i] = "";
				objExpand.innerHTML = "Click to Expand";
				RemoveChain(i);
			}
		}
	}
	SaveCookie();
}

function UpdateRate(id)
{
	var obj = eval("document.FormChoice.InputRate" + id);
	if (obj == null)
		return;
	var rate = parseFloat(obj.value);
	if (isNaN(rate))
	{
		alert("Please enter a valid interest rate");
		obj.value = FormatFloat(chnRate[id], 2);
		return;
	}
	if (rate < 0)
	{
		alert("Interest rate cannot be less than zero");
		obj.value = FormatFloat(chnRate[id], 2);
		return;
	}

	obj = eval("document.FormChoice.InputDividend" + id);
	if (obj == null)
		return;
	var div = parseFloat(obj.value);
	if (isNaN(div))
	{
		alert("Please enter a valid dividend value");
		obj.value = FormatFloat(chnD2e[id], 2);
		return;
	}
	if (div < 0)
	{
		alert("Dividend cannot be less than zero");
		obj.value = FormatFloat(chnD2e[id], 2);
		return;
	}
	if (div > 0 && chnD2e[id] == 0)
	{
		alert("Dividend value cannot be updated when there is no planned dividend distribution before the expiration date");
		obj.value = FormatFloat(chnD2e[id], 2);
		return;
	}

	chnRate[id] = rate;
	obj = eval("document.FormChoice.InputRate" + id);
	obj.value = FormatFloat(chnRate[id], 2);

	if (div >= 0 && chnD2e[id] > 0)
	{
		var ratio = div / chnD2e[id];
		for (var i = 0; i < NCHN; i++)
		{
			chnD2e[i] *= ratio;
			chnYield[i] *= ratio;
			if (chnExpireDate[i] != "" && GetChain2(i) != -1)
			{
				obj = eval("document.FormChoice.InputDividend" + i);
				if (obj != null)
					obj.value = FormatFloat(chnD2e[i], 2);
			}
		}
	}
	UpdateChains();
}

//////////////////////////////////////////////////
// Write table
// (Re)Write all tables
function WriteTables()
{
	var showAll = "Hide All";
	for (var i = 0; i < NCHN; i++)
	{
		if (GetChain2(i) == -1)
			continue;

		if (chnExpireDate[i] == "")
		{
			showAll = "Show All";
			break;
		}
	}

	var obj = document.getElementById("idTables");
	if (obj == null)
		return;
	while (obj.childNodes.length > 0)
		obj.removeChild(obj.childNodes[0]);

	for (var i = 0; i < NCHN; i++)
	{
		var ii = GetChain2(i);
		if (ii == -1)
			continue;

		// Header bar
		var table = document.createElement("table");
		table.setAttribute("width", 760);
		table.setAttribute("border", 0);
		table.setAttribute("cellPadding", 0);
		table.setAttribute("cellSpacing", 0);
		table.setAttribute("id", "idTableBar"+i);

		var tbody = document.createElement("tbody");

		var tr = document.createElement("tr");
			var td = document.createElement("td");
			td.setAttribute("width", 380);
			td.innerHTML = "<img src='http://im.morningstar.com/im/dot_clear.gif' height=5>";
			tr.appendChild(td);

			td = document.createElement("td");
			td.setAttribute("width", 380);
			td.innerHTML = "<img src='http://im.morningstar.com/im/dot_clear.gif' height=5>";
			tr.appendChild(td);
		tbody.appendChild(tr);

		tr = document.createElement("tr");
		tr.className = "BackHeaderBar";
			td = document.createElement("td");
			td.setAttribute("height", 15);
			td.className = "TextHeaderBar";
			td.innerHTML = "&nbsp;Expiration: " + chnExpireDateLong[i] + (ii == i ? "" : " - " + chnExpireDateLong[ii]);
			tr.appendChild(td);

			td = document.createElement("td");
			td.setAttribute("align", "right");
			td.className = "LinkHeaderBar";
			td.innerHTML = "<a href='javascript:ShowTable(" + i + ")' class=LinkHeaderBar><span id='idExpand" + i + "'>Click to " + (chnExpireDate[i] == "" ? "Expand" : "Hide") + "</span></a> | <a href='javascript:ShowAll(" + i + ")' class=LinkHeaderBar><span id='idShowAll" + i + "'>" + showAll + "</span></a>&nbsp";
			tr.appendChild(td);
		tbody.appendChild(tr);

		table.appendChild(tbody);
		obj.appendChild(table);

		var div = document.createElement("div");
		div.setAttribute("id", "idChain"+i);
		obj.appendChild(div);

		if (chnExpireDate[i] == "")
			continue;
		WriteChain(i);
	}
}

function RemoveChain(id)
{
	var obj = document.getElementById("idChain" + id);
	if (obj == null)
		return;
	while (obj.childNodes.length > 0)
		obj.removeChild(obj.childNodes[0]);
}

function WriteChain(id)
{
	var obj = document.getElementById("idChain" + id);
	if (obj == null)
		return;

	// Header interest
	var table = document.createElement("table");
	table.setAttribute("width", 760);
	table.setAttribute("border", 0);
	table.setAttribute("cellPadding", 0);
	table.setAttribute("cellSpacing", 0);
	table.setAttribute("id", "idTableRate"+id);

	var tbody = document.createElement("tbody");

	var tr = document.createElement("tr");
		var td = document.createElement("td");
		td.setAttribute("colSpan", 7);
		td.innerHTML = "<img src='http://im.morningstar.com/im/dot_clear.gif' height=3>";
		tr.appendChild(td);
	tbody.appendChild(tr);

	tr = document.createElement("tr");
	tr.className = "TextSmall";
		td = document.createElement("td");
		td.setAttribute("width", 152);
		td.innerHTML = "Interest Rate Assumption:";
		tr.appendChild(td);

		td = document.createElement("td");
		td.setAttribute("width", 64);
		td.innerHTML = "<input type=text size=8 name='InputRate" + id + "' value='" + FormatFloat(chnRate[id],2) + "' class=InputBox>&nbsp;%";
		tr.appendChild(td);

		td = document.createElement("td");
		td.setAttribute("width", 153);
		td.innerHTML = "Dividends Until Expiration:";
		tr.appendChild(td);

		td = document.createElement("td");
		td.setAttribute("width", 55);
		td.innerHTML = "$&nbsp;<input type=text size=8 name='InputDividend" + id + "' value='" + FormatFloat(chnD2e[id],2) + "' class=InputBox>";
		tr.appendChild(td);

		td = document.createElement("td");
		td.setAttribute("width", 96);
		td.innerHTML = "<a href='javascript:UpdateRate(" + id + ")'><img src='http://im.morningstar.com/im/OptionChain_Go.gif' border=0></a>";
		tr.appendChild(td);

		td = document.createElement("td");
		td.setAttribute("width", 20);
		td.innerHTML = "<img src='http://im.morningstar.com/im/Options_inmoneygift.gif' width=14 height=14>";
		tr.appendChild(td);

		td = document.createElement("td");
		td.setAttribute("width", 220);
		td.innerHTML = "Highlighted options are in-the-money.";
		tr.appendChild(td);
	tbody.appendChild(tr);

	tr = document.createElement("tr");
		td = document.createElement("td");
		td.setAttribute("colSpan", 7);
		td.innerHTML = "<img src='http://im.morningstar.com/im/dot_clear.gif' height=3>";
		tr.appendChild(td);
	tbody.appendChild(tr);

	table.appendChild(tbody);
	obj.appendChild(table);

	// Fair value
	if (TickerType == "E0" && fairValue > 0)
	{
		var t = chnDaysToExpire[id] / 365;
		var rfr = chnRate[id] / 100;
		var pvd = 0, pvd2 = 0;
		for (var i = 0; i < divTime.length; i++)
		{
			if (divTime[i] <= 0)
				continue;
			if (divTime[i] > t)
				break;
			pvd += divAmount[i] * Math.pow(1 + coe, t - divTime[i]);
			pvd2 += divAmount[i] * Math.exp(rfr * (t - divTime[i]));
		}
		var ffv = fairValue * Math.pow(1 + coe, t) - pvd;
		var fcb = conBuy * Math.pow(1 + coe, t) - pvd;
		var fcs = conSell * Math.pow(1 + coe, t) - pvd;
		var fp = lastPrice * Math.exp(rfr * t) - pvd2;

		table = document.createElement("table");
		table.setAttribute("width", 760);
		table.setAttribute("border", 0);
		table.setAttribute("cellPadding", 0);
		table.setAttribute("cellSpacing", 0);
		table.setAttribute("id", "idTableFFV"+id);

		tbody = document.createElement("tbody");

		tr = document.createElement("tr");
		tr.className = "TextSmall";
			td = document.createElement("td");
			td.setAttribute("width", 190);
			td.setAttribute("height", 24);
			td.innerHTML = "Future Fair Value: <a onmouseover=\"javascript:ShowHint('hintChain" + id + "|hintFFV')\" onmouseout=\"javascript:HideHint()\"><img src='http://im.morningstar.com/im/help_icon.gif' width=12 height=15 border=0></a> $<span id='idFFV" + id + "'>" + FormatFloat(ffv, 2) + "</span><div id='hintChain" + id + "'></div>";
			tr.appendChild(td);

			td = document.createElement("td");
			td.setAttribute("width", 190);
			td.innerHTML = "Future Consider Buy: <a onmouseover=\"javascript:ShowHint('hintChain" + id + "|hintFFV')\" onmouseout=\"javascript:HideHint()\"><img src='http://im.morningstar.com/im/help_icon.gif' width=12 height=15 border=0></a> $<span id='idFCB" + id + "'>" + FormatFloat(fcb, 2) + "</span>";
			tr.appendChild(td);

			td = document.createElement("td");
			td.setAttribute("width", 190);
			td.innerHTML = "Future Consider Sell: <a onmouseover=\"javascript:ShowHint('hintChain" + id + "|hintFFV')\" onmouseout=\"javascript:HideHint()\"><img src='http://im.morningstar.com/im/help_icon.gif' width=12 height=15 border=0></a> $<span id='idFCS" + id + "'>" + FormatFloat(fcs, 2) + "</span>";
			tr.appendChild(td);

			td = document.createElement("td");
			td.setAttribute("width", 190);
			td.innerHTML = "Forward Stock Price: <a onmouseover=\"javascript:ShowHint('hintChain" + id + "|hintFP')\" onmouseout=\"javascript:HideHint()\"><img src='http://im.morningstar.com/im/help_icon.gif' width=12 height=15 border=0></a> $<span id='idFP" + id + "'>" + FormatFloat(fp, 2) + "</span>";
			tr.appendChild(td);
		tbody.appendChild(tr);

		tr = document.createElement("tr");
		tr.className = "BackSep";
			td = document.createElement("td");
			td.setAttribute("colSpan", 4);
			td.innerHTML = "<img src='http://im.morningstar.com/im/dot_clear.gif' height=1>";
			tr.appendChild(td);
		tbody.appendChild(tr);

		table.appendChild(tbody);
		obj.appendChild(table);
	}

	// Options
	var div = document.createElement("div");
	div.setAttribute("id", "idOption"+id);
	obj.appendChild(div);
	WriteTable(id);
}

function RemoveTable(id)
{
	var obj = document.getElementById("idOption" + id);
	if (obj == null)
		return;
	while (obj.childNodes.length > 0)
		obj.removeChild(obj.childNodes[0]);
}

// Write table #id
function WriteTable(id)
{
	if (chnTables[id] == "")
		return;

	if (TableType == 1)
	{
		WriteTable0(id);
	}
	else
	{
		if (Layout == 0)
			WriteTable0(id);
		else
			WriteTable1(id);
	}
}

// Write table #id in stack layout
function WriteTable0(id)
{
	var bCall = document.FormChoice.chkCall.checked && colBlock[NUMCOL] == "0";
	var bPut = document.FormChoice.chkPut.checked && colBlock[NUMCOL+1] == "0";
	if (TableType == "1")
	{
		bCall = true;
		bPut = false;
	}

	var w = WSTRIKE;	//WTICKER + WSTRIKE;
	if (TableType == 2 || TableType == 4)
		w *= 2;
//	else if (TableType == 1 || TableType == 3)
//		w += WTICKER;
	for (var i = 0; i < NUMCOL; i++)
		if (colBlock[i] == "0" && colStatus[i] == "checked")
			w += colWidth[i];

	var table = document.createElement("table");
	table.setAttribute("width", w);
	table.setAttribute("border", 0);
	table.setAttribute("cellPadding", 0);
	table.setAttribute("cellSpacing", 0);
	table.setAttribute("id", "idOpTable"+id);

	var tbody = document.createElement("tbody");

	var tr, td;
	if (bCall)
	{
		// 0.
		tr = document.createElement("tr");
			td = document.createElement("td");
			if (TableType == 0 || TableType == 1 || TableType == 3)
				td.setAttribute("width", WSTRIKE);
			else
				td.setAttribute("width", WSTRIKE*2);
			td.innerHTML = "<img src='http://im.morningstar.com/im/dot_clear.gif' height=1>";
			tr.appendChild(td);

//			td = document.createElement("td");
//			if (TableType == 0)
//				td.setAttribute("width", WTICKER);
//			else
//				td.setAttribute("width", WTICKER*2);
//			td.innerHTML = "<img src='http://im.morningstar.com/im/dot_clear.gif' height=1>";
//			tr.appendChild(td);

			for (var i = 0; i < NUMCOL; i++)
			{
				if (colBlock[colOrder[i]] == "0" && colStatus[colOrder[i]] == "checked")
				{
					td = document.createElement("td");
					td.setAttribute("width", colWidth[colOrder[i]]);
					td.innerHTML = "<img src='http://im.morningstar.com/im/dot_clear.gif' height=1>";
					tr.appendChild(td);
				}
			}
		tbody.appendChild(tr);

		// 1.
		tr = document.createElement("tr");
		tr.setAttribute("vAlign", "top");
			td = document.createElement("td");
			td.setAttribute("height", 20);
			td.className = "TextCall";
			td.innerHTML = "Calls";
			tr.appendChild(td);

//			td = document.createElement("td");
//			td.className = "TextCall";
//			td.innerHTML = "&nbsp;";
//			tr.appendChild(td);

			for (var i = 0; i < NUMCOL; i++)
			{
				if (colBlock[colOrder[i]] == "0" && colStatus[colOrder[i]] == "checked")
				{
					td = document.createElement("td");
					td.className = "TextSmall";
					td.innerHTML = "&nbsp;";
					tr.appendChild(td);
				}
			}
		tbody.appendChild(tr);

		// 2.
		tr = document.createElement("tr");
			td = document.createElement("td");
			td.className = "BackSep";
			td.innerHTML = "<img src='http://im.morningstar.com/im/dot_clear.gif' height=1>";
			tr.appendChild(td);

//			td = document.createElement("td");
//			td.className = "BackSep";
//			td.innerHTML = "<img src='http://im.morningstar.com/im/dot_clear.gif' height=1>";
//			tr.appendChild(td);

			for (var i = 0; i < NUMCOL; i++)
			{
				if (colBlock[colOrder[i]] == "0" && colStatus[colOrder[i]] == "checked")
				{
					td = document.createElement("td");
					td.className = "BackSep";
					td.innerHTML = "<img src='http://im.morningstar.com/im/dot_clear.gif' height=1>";
					tr.appendChild(td);
				}
			}
		tbody.appendChild(tr);

		// 3.
		tr = document.createElement("tr");
		tr.setAttribute("align", "right");
			td = document.createElement("td");
			td.setAttribute("height", 20);
			td.className = "CellHdStrike";
			td.innerHTML = "Strike";
			tr.appendChild(td);

//			td = document.createElement("td");
//			td.setAttribute("align", "left");
//			td.className = "CellHdSymbolL";
//			td.innerHTML = "Ticker";
//			tr.appendChild(td);

			for (var i = 0; i < NUMCOL; i++)
			{
				if (colBlock[colOrder[i]] == "0" && colStatus[colOrder[i]] == "checked")
				{
					td = document.createElement("td");
					td.className = "CellHd";
					if (GreeksIn == 1 && colTitle2[colOrder[i]] != "")
						td.innerHTML = colTitle2[colOrder[i]];
					else
						td.innerHTML = colTitle[colOrder[i]];
					tr.appendChild(td);
				}
			}
		tbody.appendChild(tr);

		var options = chnTables[id].split("|");
		var nStart = 0, nEnd = options.length - 1;
		for (var i = 0; i < options.length; i++)
		{
			var col = options[i].split("^");
			var strike = parseFloat(col[0]);
			var x2s = 100 * strike / lastPrice;
			if (x2s < MoneyFrom)
				nStart++;
			else
				break;
		}
		for (var i = options.length - 1; i >= 0; i--)
		{
			var col = options[i].split("^");
			var strike = parseFloat(col[0]);
			var x2s = 100 * strike / lastPrice;
			if (x2s > MoneyTo)
				nEnd--;
			else
				break;
		}
		// 4 - # op chain + 3.
		for (var i = nStart; i <= nEnd; i++)
		{
			var col = options[i].split("^");
			var strike = parseFloat(col[0]);
			var backColor = "#FFFFFF";
			if (lastPrice > strike)
				backColor = backIM;

			tr = document.createElement("tr");
			tr.setAttribute("align", "right");
				td = document.createElement("td");
				td.setAttribute("height", 20);
				if (i == nStart)
					td.className = "CellOpStrikeU";
				else if (i == nEnd)
					td.className = "CellOpStrikeE";
				else
					td.className = "CellOpStrike";
				td.innerHTML = col[0];
				tr.appendChild(td);
/*
				td = document.createElement("td");
				td.setAttribute("bgColor", backColor);
				td.setAttribute("align", "left");
				if (col[1] == "")
				{
					if (i == nStart)
						td.className = "CellOpSymbolRU";
					else if (i == nEnd)
						td.className = "CellOpSymbolRE";
					else
						td.className = "CellOpSymbolR";
				}
				else
				{
					if (i == nStart)
						td.className = "CellOpSymbolRU2";
					else if (i == nEnd)
						td.className = "CellOpSymbolRE2";
					else
						td.className = "CellOpSymbolR2";
				}
				td.ForeColor = foreCL;
				td.curForeColor = foreCL;
				td.onclick = function() {CH_OnTicker(this);};
				if (opTickers.indexOf(","+col[2]+",") >= 0)
				{
					td.style.color = highCL;
					td.curForeColor = highCL;
				}
				td.innerHTML = col[2];
				tr.appendChild(td);
*/
				for (var j = 0; j < NUMCOL; j++)
				{
					var ii = colOrder[j];
					if (colBlock[ii] == "0" && colStatus[ii] == "checked")
					{
						td = document.createElement("td");
						td.setAttribute("bgColor", backColor);
						if (col[1] == "")
						{
							if (i == nStart)
								td.className = "CellOpRU";
							else if (i == nEnd)
								td.className = "CellOpRE";
							else
								td.className = "CellOpR";
						}
						else
						{
							if (i == nStart)
								td.className = "CellOpRU2";
							else if (i == nEnd)
								td.className = "CellOpRE2";
							else
								td.className = "CellOpR2";
						}
						var text = col[3+ii];
						if (text == "")
							text = "&nbsp;"
						td.innerHTML = text;
						tr.appendChild(td);
					}
				}
			tbody.appendChild(tr);
		}
	}

	if (bCall && bPut)
	{
		tr = document.createElement("tr");
			td = document.createElement("td");
			td.innerHTML = "<img src='http://im.morningstar.com/im/dot_clear.gif' height=10>";
			tr.appendChild(td);

			td = document.createElement("td");
			td.innerHTML = "<img src='http://im.morningstar.com/im/dot_clear.gif' height=1>";
			tr.appendChild(td);

			for (var i = 0; i < NUMCOL; i++)
			{
				if (colBlock[colOrder[i]] == "0" && colStatus[colOrder[i]] == "checked")
				{
					td = document.createElement("td");
					td.innerHTML = "<img src='http://im.morningstar.com/im/dot_clear.gif' height=1>";
					tr.appendChild(td);
				}
			}
		tbody.appendChild(tr);
	}

	if (bPut)
	{
		// 0.
		tr = document.createElement("tr");
			td = document.createElement("td");
			td.setAttribute("width", WSTRIKE);
			td.innerHTML = "<img src='http://im.morningstar.com/im/dot_clear.gif' height=1>";
			tr.appendChild(td);

//			td = document.createElement("td");
//			td.setAttribute("width", WTICKER);
//			td.innerHTML = "<img src='http://im.morningstar.com/im/dot_clear.gif' height=1>";
//			tr.appendChild(td);

			for (var i = 0; i < NUMCOL; i++)
			{
				if (colBlock[colOrder[i]] == "0" && colStatus[colOrder[i]] == "checked")
				{
					td = document.createElement("td");
					td.setAttribute("width", colWidth[colOrder[i]]);
					td.innerHTML = "<img src='http://im.morningstar.com/im/dot_clear.gif' height=1>";
					tr.appendChild(td);
				}
			}
		tbody.appendChild(tr);

		// 1.
		tr = document.createElement("tr");
		tr.setAttribute("vAlign", "top");
			td = document.createElement("td");
			td.setAttribute("height", 20);
			td.className = "TextCall";
			td.innerHTML = "Puts";
			tr.appendChild(td);

//			td = document.createElement("td");
//			td.className = "TextCall";
//			td.innerHTML = "&nbsp;";
//			tr.appendChild(td);

			for (var i = 0; i < NUMCOL; i++)
			{
				if (colBlock[colOrder[i]] == "0" && colStatus[colOrder[i]] == "checked")
				{
					td = document.createElement("td");
					td.className = "TextSmall";
					td.innerHTML = "&nbsp;";
					tr.appendChild(td);
				}
			}
		tbody.appendChild(tr);

		// 2.
		tr = document.createElement("tr");
			td = document.createElement("td");
			td.className = "BackSep";
			td.innerHTML = "<img src='http://im.morningstar.com/im/dot_clear.gif' height=1>";
			tr.appendChild(td);

//			td = document.createElement("td");
//			td.className = "BackSep";
//			td.innerHTML = "<img src='http://im.morningstar.com/im/dot_clear.gif' height=1>";
//			tr.appendChild(td);

			for (var i = 0; i < NUMCOL; i++)
			{
				if (colBlock[colOrder[i]] == "0" && colStatus[colOrder[i]] == "checked")
				{
					td = document.createElement("td");
					td.className = "BackSep";
					td.innerHTML = "<img src='http://im.morningstar.com/im/dot_clear.gif' height=1>";
					tr.appendChild(td);
				}
			}
		tbody.appendChild(tr);

		// 3.
		tr = document.createElement("tr");
		tr.setAttribute("align", "right");
			td = document.createElement("td");
			td.setAttribute("height", 20);
			td.className = "CellHdStrike";
			td.innerHTML = "Strike";
			tr.appendChild(td);

//			td = document.createElement("td");
//			td.setAttribute("align", "left");
//			td.className = "CellHdSymbolR";
//			td.innerHTML = "Ticker";
//			tr.appendChild(td);

			for (var i = 0; i < NUMCOL; i++)
			{
				if (colBlock[colOrder[i]] == "0" && colStatus[colOrder[i]] == "checked")
				{
					td = document.createElement("td");
					td.className = "CellHd";
					if (GreeksIn == 1 && colTitle2[colOrder[i]] != "")
						td.innerHTML = colTitle2[colOrder[i]];
					else
						td.innerHTML = colTitle[colOrder[i]];
					tr.appendChild(td);
				}
			}
		tbody.appendChild(tr);

		var options = chnTables[id].split("|");
		var nStart = 0, nEnd = options.length - 1;
		for (var i = 0; i < options.length; i++)
		{
			var col = options[i].split("^");
			var strike = parseFloat(col[0]);
			var x2s = 100 * strike / lastPrice;
			if (x2s < MoneyFrom)
				nStart++;
			else
				break;
		}
		for (var i = options.length - 1; i >= 0; i--)
		{
			var col = options[i].split("^");
			var strike = parseFloat(col[0]);
			var x2s = 100 * strike / lastPrice;
			if (x2s > MoneyTo)
				nEnd--;
			else
				break;
		}
		// 4 - # op chain + 3.
		var NP = NUMCOL + 2;
		for (var i = nStart; i <= nEnd; i++)
		{
			var col = options[i].split("^");
			var strike = parseFloat(col[0]);
			var backColor = "#FFFFFF";
			if (lastPrice < strike)
				backColor = backIM;

			tr = document.createElement("tr");
			tr.setAttribute("align", "right");
				td = document.createElement("td");
				td.setAttribute("height", 20);
				if (i == nStart)
					td.className = "CellOpStrikeU";
				else if (i == nEnd)
					td.className = "CellOpStrikeE";
				else
					td.className = "CellOpStrike";
				td.innerHTML = col[0];
				tr.appendChild(td);
/*
				td = document.createElement("td");
				td.setAttribute("bgColor", backColor);
				td.setAttribute("align", "left");
				if (col[1+NP] == "")
				{
					if (i == nStart)
						td.className = "CellOpSymbolRU";
					else if (i == nEnd)
						td.className = "CellOpSymbolRE";
					else
						td.className = "CellOpSymbolR";
				}
				else
				{
					if (i == nStart)
						td.className = "CellOpSymbolRU2";
					else if (i == nEnd)
						td.className = "CellOpSymbolRE2";
					else
						td.className = "CellOpSymbolR2";
				}
				td.ForeColor = foreCL;
				td.curForeColor = foreCL;
				td.onclick = function() {CH_OnTicker(this);};
				if (opTickers.indexOf(","+col[2+NP]+",") >= 0)
				{
					td.style.color = highCL;
					td.curForeColor = highCL;
				}
				td.innerHTML = col[2+NP];
				tr.appendChild(td);
*/
				for (var j = 0; j < NUMCOL; j++)
				{
					var ii = colOrder[j];
					if (colBlock[ii] == "0" && colStatus[ii] == "checked")
					{
						td = document.createElement("td");
						td.setAttribute("bgColor", backColor);
						if (col[1+NP] == "")
						{
							if (i == nStart)
								td.className = "CellOpRU";
							else if (i == nEnd)
								td.className = "CellOpRE";
							else
								td.className = "CellOpR";
						}
						else
						{
							if (i == nStart)
								td.className = "CellOpRU2";
							else if (i == nEnd)
								td.className = "CellOpRE2";
							else
								td.className = "CellOpR2";
						}
						var text = col[3+ii+NP];
						if (text == "")
							text = "&nbsp;"
						td.innerHTML = text;
						tr.appendChild(td);
					}
				}
			tbody.appendChild(tr);
		}
	}

	table.appendChild(tbody);

	var obj = document.getElementById("idOption" + id);
	if (obj != null)
		obj.appendChild(table);
}

// Write table #id in butterfly layout
function WriteTable1(id)
{
	// If only show calls, then move strike column in the first.
	var bCall = document.FormChoice.chkCall.checked && colBlock[NUMCOL] == "0";
	var bPut = document.FormChoice.chkPut.checked && colBlock[NUMCOL+1] == "0";
	var bStrike = bCall && !bPut;

	var w = WSTRIKE;
	if (TableType == 2 || TableType == 4)
		w += WSTRIKE;
	if (bCall)
	{
//		w += WTICKER;
//		if (TableType != 0)
//			w += WTICKER;
		for (var i = 0; i < NUMCOL; i++)
			if (colBlock[i] == "0" && colStatus[i] == "checked")
				w += colWidth[i];
	}
	if (bPut)
	{
//		w += WTICKER;
//		if (TableType != 0)
//			w += WTICKER;
		for (var i = 0; i < NUMCOL; i++)
			if (colBlock[i] == "0" && colStatus[i] == "checked")
				w += colWidth[i];
	}

	var table = document.createElement("table");
	table.setAttribute("width", w);
	table.setAttribute("border", 0);
	table.setAttribute("cellPadding", 0);
	table.setAttribute("cellSpacing", 0);
	table.setAttribute("id", "idOpTable"+id);

	var tbody = document.createElement("tbody");

	// 0.
	var td;
	var tr = document.createElement("tr");
		if (bStrike)
		{
			td = document.createElement("td");
			if (TableType == 0 || TableType == 3)
				td.setAttribute("width", WSTRIKE);
			else
				td.setAttribute("width", WSTRIKE*2);
			td.innerHTML = "<img src='http://im.morningstar.com/im/dot_clear.gif' height=1>";
			tr.appendChild(td);
		}

		if (bCall)
		{
//			td = document.createElement("td");
//			if (TableType == 0)
//				td.setAttribute("width", WTICKER);
//			else
//				td.setAttribute("width", WTICKER*2);
//			td.innerHTML = "<img src='http://im.morningstar.com/im/dot_clear.gif' height=1>";
//			tr.appendChild(td);

			for (var i = 0; i < NUMCOL; i++)
			{
				if (colBlock[colOrder[i]] == "0" && colStatus[colOrder[i]] == "checked")
				{
					td = document.createElement("td");
					td.setAttribute("width", colWidth[colOrder[i]]);
					td.innerHTML = "<img src='http://im.morningstar.com/im/dot_clear.gif' height=1>";
					tr.appendChild(td);
				}
			}
		}

		if (!bStrike)
		{
			td = document.createElement("td");
			if (TableType == 0 || TableType == 3)
				td.setAttribute("width", WSTRIKE);
			else
				td.setAttribute("width", WSTRIKE*2);
			td.innerHTML = "<img src='http://im.morningstar.com/im/dot_clear.gif' height=1>";
			tr.appendChild(td);
		}

		if (bPut)
		{
//			td = document.createElement("td");
//			if (TableType == 0)
//				td.setAttribute("width", WTICKER);
//			else
//				td.setAttribute("width", WTICKER*2);
//			td.innerHTML = "<img src='http://im.morningstar.com/im/dot_clear.gif' height=1>";
//			tr.appendChild(td);

			for (var i = 0; i < NUMCOL; i++)
			{
				if (colBlock[colOrder[i]] == "0" && colStatus[colOrder[i]] == "checked")
				{
					td = document.createElement("td");
					td.setAttribute("width", colWidth[colOrder[i]]);
					td.innerHTML = "<img src='http://im.morningstar.com/im/dot_clear.gif' height=1>";
					tr.appendChild(td);
				}
			}
		}
	tbody.appendChild(tr);

	// 1.
	tr = document.createElement("tr");
	tr.setAttribute("vAlign", "top");
		if (bStrike)
		{
			td = document.createElement("td");
			td.setAttribute("height", 20);
			td.className = "TextCall";
			td.innerHTML = "&nbsp;";
			tr.appendChild(td);
		}

		if (bCall)
		{
			td = document.createElement("td");
			td.className = "TextCall";
			td.innerHTML = "Calls";
			tr.appendChild(td);

			for (var i = 0; i < NUMCOL; i++)
			{
				if (colBlock[colOrder[i]] == "0" && colStatus[colOrder[i]] == "checked")
				{
					td = document.createElement("td");
					td.className = "TextSmall";
					td.innerHTML = "&nbsp;";
					tr.appendChild(td);
				}
			}
		}

		if (!bStrike)
		{
			td = document.createElement("td");
			td.setAttribute("height", 20);
			td.className = "TextCall";
			td.innerHTML = "&nbsp;";
			tr.appendChild(td);
		}

		if (bPut)
		{
			td = document.createElement("td");
			td.className = "TextCall";
			td.innerHTML = "Puts";
			tr.appendChild(td);

			for (var i = 0; i < NUMCOL; i++)
			{
				if (colBlock[colOrder[i]] == "0" && colStatus[colOrder[i]] == "checked")
				{
					td = document.createElement("td");
					td.className = "TextSmall";
					td.innerHTML = "&nbsp;";
					tr.appendChild(td);
				}
			}
		}
	tbody.appendChild(tr);

	// 2.
	tr = document.createElement("tr");
		if (bStrike)
		{
			td = document.createElement("td");
			td.innerHTML = "<img src='http://im.morningstar.com/im/dot_clear.gif' height=1>";
			tr.appendChild(td);
		}

		if (bCall)
		{
//			td = document.createElement("td");
//			td.className = "BackSep";
//			td.innerHTML = "<img src='http://im.morningstar.com/im/dot_clear.gif' height=1>";
//			tr.appendChild(td);

			for (var i = 0; i < NUMCOL; i++)
			{
				if (colBlock[colOrder[i]] == "0" && colStatus[colOrder[i]] == "checked")
				{
					td = document.createElement("td");
					td.className = "BackSep";
					td.innerHTML = "<img src='http://im.morningstar.com/im/dot_clear.gif' height=1>";
					tr.appendChild(td);
				}
			}
		}

		if (!bStrike)
		{
			td = document.createElement("td");
			td.innerHTML = "<img src='http://im.morningstar.com/im/dot_clear.gif' height=1>";
			tr.appendChild(td);
		}

		if (bPut)
		{
//			td = document.createElement("td");
//			td.className = "BackSep";
//			td.innerHTML = "<img src='http://im.morningstar.com/im/dot_clear.gif' height=1>";
//			tr.appendChild(td);

			for (var i = 0; i < NUMCOL; i++)
			{
				if (colBlock[colOrder[i]] == "0" && colStatus[colOrder[i]] == "checked")
				{
					td = document.createElement("td");
					td.className = "BackSep";
					td.innerHTML = "<img src='http://im.morningstar.com/im/dot_clear.gif' height=1>";
					tr.appendChild(td);
				}
			}
		}
	tbody.appendChild(tr);

	// 3.
	tr = document.createElement("tr");
	tr.setAttribute("align", "right");
		if (bStrike)
		{
			td = document.createElement("td");
			td.setAttribute("height", 20);
			td.className = "CellHdStrike";
			td.innerHTML = "Strike";
			tr.appendChild(td);
		}

		if (bCall)
		{
//			td = document.createElement("td");
//			td.setAttribute("align", "left");
//			td.className = "CellHdSymbolL";
//			td.innerHTML = "Ticker";
//			tr.appendChild(td);

			for (var i = 0; i < NUMCOL; i++)
			{
				if (colBlock[colOrder[i]] == "0" && colStatus[colOrder[i]] == "checked")
				{
					td = document.createElement("td");
					td.className = "CellHd";
					if (GreeksIn == 1 && colTitle2[colOrder[i]] != "")
						td.innerHTML = colTitle2[colOrder[i]];
					else
						td.innerHTML = colTitle[colOrder[i]];
					tr.appendChild(td);
				}
			}
		}

		if (!bStrike)
		{
			td = document.createElement("td");
			td.setAttribute("height", 20);
			td.className = "CellHdStrike";
			td.innerHTML = "Strike";
			tr.appendChild(td);
		}

		if (bPut)
		{
//			td = document.createElement("td");
//			td.setAttribute("align", "left");
//			td.className = "CellHdSymbolR";
//			td.innerHTML = "Ticker";
//			tr.appendChild(td);

			for (var i = 0; i < NUMCOL; i++)
			{
				if (colBlock[colOrder[i]] == "0" && colStatus[colOrder[i]] == "checked")
				{
					td = document.createElement("td");
					td.className = "CellHd";
					if (GreeksIn == 1 && colTitle2[colOrder[i]] != "")
						td.innerHTML = colTitle2[colOrder[i]];
					else
						td.innerHTML = colTitle[colOrder[i]];
					tr.appendChild(td);
				}
			}
		}
	tbody.appendChild(tr);

	var options = chnTables[id].split("|");
	var nStart = 0, nEnd = options.length - 1;
	for (var i = 0; i < options.length; i++)
	{
		var col = options[i].split("^");
		var strike = parseFloat(col[0]);
		var x2s = 100 * strike / lastPrice;
		if (x2s < MoneyFrom)
			nStart++;
		else
			break;
	}
	for (var i = options.length - 1; i >= 0; i--)
	{
		var col = options[i].split("^");
		var strike = parseFloat(col[0]);
		var x2s = 100 * strike / lastPrice;
		if (x2s > MoneyTo)
			nEnd--;
		else
			break;
	}
	// 4 - # op chain + 3.
	var NP = NUMCOL + 2;
	for (var i = nStart; i <= nEnd; i++)
	{
		var col = options[i].split("^");
		var strike = parseFloat(col[0]);

		tr = document.createElement("tr");
		tr.setAttribute("align", "right");
			if (bStrike)
			{
				td = document.createElement("td");
				td.setAttribute("height", 20);
				if (i == nStart)
					td.className = "CellOpStrikeU";
				else if (i == nEnd)
					td.className = "CellOpStrikeE";
				else
					td.className = "CellOpStrike";
				td.innerHTML = col[0];
				tr.appendChild(td);
			}

			if (bCall)
			{
				var backColor = "#FFFFFF";
				if (lastPrice > strike)
					backColor = backIM;
/*
				td = document.createElement("td");
				td.setAttribute("bgColor", backColor);
				td.setAttribute("align", "left");
				if (col[1] == "")
				{
					if (i == nStart)
						td.className = "CellOpSymbolLU";
					else if (i == nEnd)
						td.className = "CellOpSymbolLE";
					else
						td.className = "CellOpSymbolL";
				}
				else
				{
					if (i == nStart)
						td.className = "CellOpSymbolLU2";
					else if (i == nEnd)
						td.className = "CellOpSymbolLE2";
					else
						td.className = "CellOpSymbolL2";
				}
				td.innerHTML = col[2];
				tr.appendChild(td);
*/
				for (var j = 0; j < NUMCOL; j++)
				{
					var ii = colOrder[j];
					if (colBlock[ii] == "0" && colStatus[ii] == "checked")
					{
						td = document.createElement("td");
						td.setAttribute("bgColor", backColor);
						if (col[1] == "")
						{
							if (i == nStart)
								td.className = "CellOpLU";
							else if (i == nEnd)
								td.className = "CellOpLE";
							else
								td.className = "CellOpL";
						}
						else
						{
							if (i == nStart)
								td.className = "CellOpLU2";
							else if (i == nEnd)
								td.className = "CellOpLE2";
							else
								td.className = "CellOpL2";
						}
						var text = col[3+ii];
						if (text == "")
							text = "&nbsp;"
						td.innerHTML = text;
						tr.appendChild(td);
					}
				}
			}

			if (!bStrike)
			{
				td = document.createElement("td");
				td.setAttribute("height", 20);
				if (i == nStart)
					td.className = "CellOpStrikeU";
				else if (i == nEnd)
					td.className = "CellOpStrikeE";
				else
					td.className = "CellOpStrike";
				td.innerHTML = col[0];
				tr.appendChild(td);
			}

			if (bPut)
			{
				var backColor = "#FFFFFF";
				if (lastPrice < strike)
					backColor = backIM;
/*
				td = document.createElement("td");
				td.setAttribute("bgColor", backColor);
				td.setAttribute("align", "left");
				if (col[1+NP] == "")
				{
					if (i == nStart)
						td.className = "CellOpSymbolRU";
					else if (i == nEnd)
						td.className = "CellOpSymbolRE";
					else
						td.className = "CellOpSymbolR";
				}
				else
				{
					if (i == nStart)
						td.className = "CellOpSymbolRU2";
					else if (i == nEnd)
						td.className = "CellOpSymbolRE2";
					else
						td.className = "CellOpSymbolR2";
				}
				td.innerHTML = col[2+NP];
				tr.appendChild(td);
*/
				for (j = 0; j < NUMCOL; j++)
				{
					ii = colOrder[j];
					if (colBlock[ii] == "0" && colStatus[ii] == "checked")
					{
						td = document.createElement("td");
						td.setAttribute("bgColor", backColor);
						if (col[1+NP] == "")
						{
							if (i == nStart)
								td.className = "CellOpRU";
							else if (i == nEnd)
								td.className = "CellOpRE";
							else
								td.className = "CellOpR";
						}
						else
						{
							if (i == nStart)
								td.className = "CellOpRU2";
							else if (i == nEnd)
								td.className = "CellOpRE2";
							else
								td.className = "CellOpR2";
						}
						var text = col[3+ii+NP];
						if (text == "")
							text = "&nbsp;";
						td.innerHTML = text;
						tr.appendChild(td);
					}
				}
			}
		tbody.appendChild(tr);
	}
	table.appendChild(tbody);

	var obj = document.getElementById("idOption" + id);
	if (obj != null)
		obj.appendChild(table);
}

// Flip option table columns.
function Flip(id)
{
	if (TableType == 1)
	{
		Flip0(id);
	}
	else
	{
		if (Layout == 0)
			Flip0(id);
		else
			Flip1(id);
	}
}

// Switch checkbox for stack option table. id is column ID.
function Flip0(id)
{
	var ii = 0;
	colStatus[id] = "checked";
	for (var i = 0; i < colOrder.length; i++)
	{
		if (colBlock[colOrder[i]] == "0" && colStatus[colOrder[i]] == "checked")
		{
			ii++;
			if (colOrder[i] == id)
				break;
		}
	}

	var objChk = eval("document.FormChoice." + colName[id]);
	if (!objChk.checked)
		colStatus[id] = "";

	var bCall = document.FormChoice.chkCall.checked && colBlock[NUMCOL] == "0";
	var bPut = document.FormChoice.chkPut.checked && colBlock[NUMCOL+1] == "0";
	if (TableType == 1)
	{
		bCall = true;
		bPut = false;
	}

	var w = WSTRIKE;	//WTICKER + WSTRIKE;
	if (TableType == 2 || TableType == 4)
		w *= 2;
//	else if (TableType == 1 || TableType == 3)
//		w += WTICKER;
	for (var i = 0; i < NUMCOL; i++)
		if (colBlock[i] == "0" && colStatus[i] == "checked")
			w += colWidth[i];

	var greeks2 = false;
	if (GreeksIn == 1 && colTitle2[id] != "")
		greeks2 = true;

	for (var i = 0; i < NCHN; i++)
	{
		if (chnExpireDate[i] == "" || GetChain2(i) == -1 || chnTables[i] == "")
			continue;

		var objTable = document.getElementById("idOpTable" + i);
		if (objTable == null)
			continue;
		objTable.setAttribute("width", w);
		var rows = objTable.getElementsByTagName("tr");

		if (objChk.checked)
		{
			var options = chnTables[i].split("|");
			var nStart = 0, nEnd = options.length - 1;
			for (var j = 0; j < options.length; j++)
			{
				var col = options[j].split("^");
				var strike = parseFloat(col[0]);
				var x2s = 100 * strike / lastPrice;
				if (x2s < MoneyFrom)
					nStart++;
				else
					break;
			}
			for (var j = options.length - 1; j >= 0; j--)
			{
				var col = options[j].split("^");
				var strike = parseFloat(col[0]);
				var x2s = 100 * strike / lastPrice;
				if (x2s > MoneyTo)
					nEnd--;
				else
					break;
			}

			// Put row offset
			var jj = 0, cell;
			if (bCall)
				jj += nEnd - nStart + 6;

			if (bCall)
			{
				cell = rows[0].insertCell(ii);
				cell.innerHTML = "<img src='http://im.morningstar.com/im/dot_clear.gif'>";
				cell.setAttribute("width", colWidth[id]);

				cell = rows[1].insertCell(ii);
				cell.innerHTML = "&nbsp;";
				cell.className = "TextSmall";

				cell = rows[2].insertCell(ii);
				cell.innerHTML = "<img src='http://im.morningstar.com/im/dot_clear.gif' height=1>";
				cell.className = "BackSep";

				cell = rows[3].insertCell(ii);
				if (greeks2)
					cell.innerHTML = colTitle2[id];
				else
					cell.innerHTML = colTitle[id];
				cell.className = "CellHd";
			}

			if (bCall && bPut)
			{
				cell = rows[jj-1].insertCell(ii);
				cell.innerHTML = "<img src='http://im.morningstar.com/im/dot_clear.gif'>";
			}

			if (bPut)
			{
				cell = rows[jj].insertCell(ii);
				cell.innerHTML = "<img src='http://im.morningstar.com/im/dot_clear.gif'>";
				cell.setAttribute("width", colWidth[id]);

				cell = rows[jj+1].insertCell(ii);
				cell.innerHTML = "&nbsp;";
				cell.className = "TextSmall";

				cell = rows[jj+2].insertCell(ii);
				cell.innerHTML = "<img src='http://im.morningstar.com/im/dot_clear.gif' height=1>";
				cell.className = "BackSep";

				cell = rows[jj+3].insertCell(ii);
				if (greeks2)
					cell.innerHTML = colTitle2[id];
				else
					cell.innerHTML = colTitle[id];
				cell.className = "CellHd";
			}

			var NP = NUMCOL + 2, id1 = id + 3, id2 = id1 + NP;
			var k = 3;
			for (var j = nStart; j <= nEnd; j++)
			{
				k++;
				var col = options[j].split("^");
				var strike = parseFloat(col[0]);

				if (bCall)
				{
					var backColor = "#FFFFFF";
					if (lastPrice > strike)
						backColor = backIM;

					cell = rows[k].insertCell(ii);
					cell.setAttribute("bgColor", backColor);
					if (col[1] == "")
					{
						if (j == nStart)
							cell.className = "CellOpRU";
						else if (j == nEnd)
							cell.className = "CellOpRE";
						else
							cell.className = "CellOpR";
					}
					else
					{
						if (j == nStart)
							cell.className = "CellOpRU2";
						else if (j == nEnd)
							cell.className = "CellOpRE2";
						else
							cell.className = "CellOpR2";
					}
					if (col[id1] == "")
						cell.innerHTML = "&nbsp;";
					else
						cell.innerHTML = col[id1];
				}
				if (bPut)
				{
					var backColor = "#FFFFFF";
					if (lastPrice < strike)
						backColor = backIM;

					cell = rows[k+jj].insertCell(ii);
					cell.setAttribute("bgColor", backColor);
					if (col[1+NP] == "")
					{
						if (j == nStart)
							cell.className = "CellOpRU";
						else if (j == nEnd)
							cell.className = "CellOpRE";
						else
							cell.className = "CellOpR";
					}
					else
					{
						if (j == nStart)
							cell.className = "CellOpRU2";
						else if (j == nEnd)
							cell.className = "CellOpRE2";
						else
							cell.className = "CellOpR2";
					}
					if (col[id2] == "")
						cell.innerHTML = "&nbsp;";
					else
						cell.innerHTML = col[id2];
				}
			}
		}
		else
		{
			for (var j = 0; j < rows.length; j++)
				rows[j].deleteCell(ii);
		}
	}
}

// Switch checkbox for butterfly option table. id is column ID.
function Flip1(id)
{
	// ii2: put column position
	var ii2 = 1;//2;
	for (var i = 0; i < colStatus.length; i++)
		if (colBlock[i] == "0" && colStatus[i] == "checked")
			ii2++;

	// Find call column position: ii.
	var ii = -1;//0;
	colStatus[id] = "checked";
	for (var i = 0; i < colOrder.length; i++)
	{
		if (colBlock[colOrder[i]] == "0" && colStatus[colOrder[i]] == "checked")
		{
			ii++;
			if (colOrder[i] == id)
				break;
		}
	}
	ii2 += ii;

	// Set column status
	var objChk = eval("document.FormChoice." + colName[id]);
	if (!objChk.checked)
		colStatus[id] = "";

	// Calls/Puts column status to decide the position of strike column and adjust column position
	var bCall = document.FormChoice.chkCall.checked && colBlock[NUMCOL] == "0";
	var bPut = document.FormChoice.chkPut.checked && colBlock[NUMCOL+1] == "0";
	var bStrike = bCall && !bPut;
	if (bStrike)
		ii++;
	if (!bCall && bPut)
		ii2 = ii + 1;

	var w = WSTRIKE;
	if (TableType == 2 || TableType == 4)
		w += WSTRIKE;
	if (bCall)
	{
//		w += WTICKER;
//		if (TableType != 0)
//			w += WTICKER;
		for (var i = 0; i < NUMCOL; i++)
			if (colBlock[i] == "0" && colStatus[i] == "checked")
				w += colWidth[i];
	}
	if (bPut)
	{
//		w += WTICKER;
//		if (TableType != 0)
//			w += WTICKER;
		for (var i = 0; i < NUMCOL; i++)
			if (colBlock[i] == "0" && colStatus[i] == "checked")
				w += colWidth[i];
	}

	// Whether it's percentage greeks
	var greeks2 = false;
	if (GreeksIn == 1 && colTitle2[id] != "")
		greeks2 = true;

	for (var i = 0; i < NCHN; i++)
	{
		if (chnExpireDate[i] == "" || GetChain2(i) == -1 || chnTables[i] == "")
			continue;

		var objTable = document.getElementById("idOpTable" + i);
		if (objTable == null)
			continue;
		objTable.setAttribute("width", w);
		var rows = objTable.getElementsByTagName("tr");

		if (objChk.checked)
		{
			var cell;
			if (bPut)
			{
				cell = rows[0].insertCell(ii2);
				cell.innerHTML = "<img src='http://im.morningstar.com/im/dot_clear.gif' height=1>";
				cell.setAttribute("width", colWidth[id]);
			}
			if (bCall)
			{
				cell = rows[0].insertCell(ii);
				cell.innerHTML = "<img src='http://im.morningstar.com/im/dot_clear.gif' height=1>";
				cell.setAttribute("width", colWidth[id]);
			}

			if (bPut)
			{
				cell = rows[1].insertCell(ii2);
				cell.innerHTML = "&nbsp;";
				cell.className = "TextSmall";
			}
			if (bCall)
			{
				cell = rows[1].insertCell(ii);
				cell.innerHTML = "&nbsp;";
				cell.className = "TextSmall";
			}

			if (bPut)
			{
				cell = rows[2].insertCell(ii2);
				cell.innerHTML = "<img src='http://im.morningstar.com/im/dot_clear.gif' height=1>";
				cell.className = "BackSep";
			}
			if (bCall)
			{
				cell = rows[2].insertCell(ii);
				cell.innerHTML = "<img src='http://im.morningstar.com/im/dot_clear.gif' height=1>";
				cell.className = "BackSep";
			}

			if (bPut)
			{
				cell = rows[3].insertCell(ii2);
				if (greeks2)
					cell.innerHTML = colTitle2[id];
				else
					cell.innerHTML = colTitle[id];
				cell.className = "CellHd";
			}
			if (bCall)
			{
				cell = rows[3].insertCell(ii);
				if (greeks2)
					cell.innerHTML = colTitle2[id];
				else
					cell.innerHTML = colTitle[id];
				cell.className = "CellHd";
			}

			var options = chnTables[i].split("|");
			var nStart = 0, nEnd = options.length - 1;
			for (var j = 0; j < options.length; j++)
			{
				var col = options[j].split("^");
				var strike = parseFloat(col[0]);
				var x2s = 100 * strike / lastPrice;
				if (x2s < MoneyFrom)
					nStart++;
				else
					break;
			}
			for (var j = options.length - 1; j >= 0; j--)
			{
				var col = options[j].split("^");
				var strike = parseFloat(col[0]);
				var x2s = 100 * strike / lastPrice;
				if (x2s > MoneyTo)
					nEnd--;
				else
					break;
			}

			// id1: call index, id2: put index
			var NP = NUMCOL + 2, id1 = id + 3, id2 = id1 + NP;
			var k = 3;
			for (var j = nStart; j <= nEnd; j++)
			{
				k++;
				var col = options[j].split("^");
				var strike = parseFloat(col[0]);
				if (bPut)
				{
					var backColor = "#FFFFFF";
					if (lastPrice < strike)
						backColor = backIM;

					cell = rows[k].insertCell(ii2);
					cell.setAttribute("bgColor", backColor);
					if (col[1+NP] == "")
					{
						if (j == nStart)
							cell.className = "CellOpRU";
						else if (j == nEnd)
							cell.className = "CellOpRE";
						else
							cell.className = "CellOpR";
					}
					else
					{
						if (j == nStart)
							cell.className = "CellOpRU2";
						else if (j == nEnd)
							cell.className = "CellOpRE2";
						else
							cell.className = "CellOpR2";
					}
					if (col[id2] == "")
						cell.innerHTML = "&nbsp;";
					else
						cell.innerHTML = col[id2];
				}
				if (bCall)
				{
					var backColor = "#FFFFFF";
					if (lastPrice > strike)
						backColor = backIM;

					cell = rows[k].insertCell(ii);
					cell.setAttribute("bgColor", backColor);
					if (col[1] == "")
					{
						if (j == nStart)
							cell.className = "CellOpLU";
						else if (j == nEnd)
							cell.className = "CellOpLE";
						else
							cell.className = "CellOpL";
					}
					else
					{
						if (j == nStart)
							cell.className = "CellOpLU2";
						else if (j == nEnd)
							cell.className = "CellOpLE2";
						else
							cell.className = "CellOpL2";
					}
					if (col[id1] == "")
						cell.innerHTML = "&nbsp;";
					else
						cell.innerHTML = col[id1];
				}
			}
		}
		else
		{
			for (var j = 0; j < rows.length; j++)
			{
				if (bPut)
					rows[j].deleteCell(ii2);
				if (bCall)
					rows[j].deleteCell(ii);
			}
		}
	}
}

//////////////////////////////////////////////////
// Calculate table values
function CalTables(bv)
{
	var table = new Array();
	for (var i = 0; i < NCHN; i++)
	{
		if (GetChain2(i) == -1)
			continue;

		table[i] = CalATable(i, bv);;
	}
	strTables = table.join("~");
	chnTables = strTables.split("~");
}

function CalATable(id, bv)
{
	if (chnExpireDate[id] == "" || chnOptions[id] == "")
		return "";

	if		(TableType == 0)	return CalATables0(id, bv);
	else if (TableType == 1)	return CalATables1(id, bv);
	else if (TableType == 2)	return CalATables2(id, bv);
	else if (TableType == 3)	return CalATables2(id, bv);
	else if (TableType == 4)	return CalATables2(id, bv);
}

function CalATables0(id, bv)
{
	var NP = NUMCOL + 2;
	var exptime = (chnDaysToExpire[id] + 1) / 365;
	var exptime0 = (chnDaysToExpire[id] + day2Close + 1) / 365;
	var irate = chnRate[id] / 100;
	var yield = chnYield[id] / 100;
	var st = Math.sqrt(exptime);
	var p1 = lastPrice * Math.exp(-yield * exptime);
	var eqt = Math.exp(-yield * exptime);
	var ert = Math.exp(-irate * exptime);
	var spi = Math.sqrt(2 * Math.PI);

	var options = chnOptions[id].split("|");
	var row = new Array();

	for (var j = 0; j < options.length; j++)
	{
		var record = options[j].split(",");
		var col = new Array(NUMCOL*2+5);

		var strike = parseFloat(record[0]);
		col[0] = FormatFloat(strike, 2);

		var du = Math.log(lastPrice/strike) + (irate-yield) * exptime;
		var x1 = strike * Math.exp(-irate * exptime);

		// Call
		var flag = record[1].substring(EndPoint, EndPoint+1);
		var ticker = record[2];
		var last = record[3];
		var bid = record[4] == "N" ? -1 : parseFloat(record[4]);
		var ask = record[5] == "N" ? -1 : parseFloat(record[5]);
		var bid0 = record[6] == "N" ? -1 : parseFloat(record[6]);
		var ask0 = record[7] == "N" ? -1 : parseFloat(record[7]);
		var volume = record[8] == "N" ? -1 : parseInt(record[8]);
		var open = record[9] == "N" ? -1 : parseInt(record[9]);
		var open0 = record[10] == "N" ? -1 : parseInt(record[10]);

		var mid = -1, mid0 = -1;
		if (bid >= 0 && ask >= 0)
			mid = (bid + ask) / 2;
		if (bid0 >= 0 && ask0 >= 0)
			mid0 = (bid0 + ask0) / 2;

		var change = "N";
		if ((EndPoint == 0) && mid0 >= 0 && mid >= 0)
			change = mid - mid0;
		else if ((EndPoint == 1) && bid0 >= 0 && bid >= 0)
			change = bid - bid0;
		else if ((EndPoint == 2) && ask0 >= 0 && ask >= 0)
			change = ask - ask0;

		var changeOpen = "N";
		if (open >= 0 && open0 >= 0)
			changeOpen = open - open0;

		var oprice = -1;
		if (flag == "N")
		{
			if (EndPoint == 0 && mid >= 0)
				oprice = mid;
			else if (EndPoint == 1 && bid >= 0)
				oprice = bid;
			else if (EndPoint == 2 && ask >= 0)
				oprice = ask;
		}

		var money = 100 * strike / lastPrice;
		var intValue = Math.max(lastPrice-strike, 0);
		var timeValue = oprice < 0 ? -1 : oprice - intValue;
		var annPrem = oprice < 0 ? -1 : 100 * Math.log(1 + oprice / strike) / exptime;
		var annTime = timeValue < 0 ? -1 : 100 * Math.log(1 + timeValue / strike) / exptime;
		var breakEven = oprice < 0 ? -200 : ((strike + oprice) / lastPrice - 1) * 100;

		col[1] = flag == "N" ? "" : flag;
		col[2] = ticker;
		col[3] = last == "N" ? "N/A" : last;
		col[4] = change == "N" ? "N/A" : FormatChange(change, 2);
		col[5] = bid < 0 ? "N/A" : FormatFloat(bid, 2);
		col[6] = ask < 0 ? "N/A" : FormatFloat(ask, 2);
		col[7] = volume < 0 ? "N/A" : FormatLong(volume);
		col[8] = open < 0 ? "N/A" : FormatLong(open);
		col[15] = FormatFloat(money, 0);
		col[16] = FormatFloat(intValue, 2);
		col[17] = timeValue < 0 ? "" : FormatFloat(timeValue, 2);
		col[18] = annPrem < 0 ? "" : FormatFloat(annPrem, 2);
		col[19] = annTime < 0 ? "" : FormatFloat(annTime, 2);
		col[21] = breakEven < -100 ? "" : FormatFloat(breakEven, 2);
		col[26] = changeOpen == "N" ? "N/A" : FormatLong(changeOpen);
		col[29] = mid < 0 ? "N/A" : FormatFloat(mid, 2);

		var ivol = -1;
		if (oprice > 0)
			ivol = IV(lastPrice, strike, exptime, irate, yield, 0, oprice);

		if (ivol > 0)
		{
			var d1 = (du + ivol * ivol * exptime / 2) / (ivol * st);
			var d2 = d1 - ivol * st;
			var Nd1 = NormDist(d1);
			var Nd2 = NormDist(d2);
			var nd1 = Math.exp(-0.5 * d1 * d1) / spi;

			var delta = eqt * Nd1;
			var gamma = nd1 * eqt / (lastPrice * ivol * st);
			var vega = p1 * st * nd1 / 100;
			var rho = exptime * x1 * Nd2 / 100;
			var theta = (-p1 * nd1 * ivol / (2 * st) + yield * p1 * Nd1 - irate * x1 * Nd2) / 365;
			var probIM = NormDist((Math.log(lastPrice/(strike+oprice)) + (irate-yield-ivol*ivol/2)*exptime) / (ivol*st)) * 100;
			var moe = -1;
			if (mid > 0)
				moe = (ask - bid) * 100 * oprice / (mid * delta * lastPrice);
			if (GreeksIn == 1)
			{
				gamma *= lastPrice / delta;
				delta *= lastPrice / oprice;
				vega *= ivol * 100 / oprice;
				rho *= 100 / oprice;
				theta *= 100 / oprice;
			}
			var delta2theta = "N";
			if (theta != 0)
				delta2theta = delta / theta;

			var oprice0 = -1;
			if (flag == "N")
			{
				if (EndPoint == 0 && mid0 >= 0)
					oprice0 = mid0;
				else if (EndPoint == 1 && bid0 >= 0)
					oprice0 = bid0;
				else if (EndPoint == 2 && ask0 >= 0)
					oprice0 = ask0;
			}

			var ivol0 = -1;
			if (oprice0 > 0)
				ivol0 = IV(closePrice, strike, exptime0, irate, yield, 0, oprice0);
			if (ivol0 > 0)
			{
				var changeS = OptionPrice(lastPrice, strike, exptime0, ivol0, irate, yield, 0) - oprice0;
				var changeV = OptionPrice(closePrice, strike, exptime0, ivol, irate, yield, 0) - oprice0;
				var changeT = OptionPrice(closePrice, strike, exptime, ivol0, irate, yield, 0) - oprice0;
				var changeR = oprice - oprice0 - changeS - changeV - changeT;
				var changeIV = (ivol - ivol0) * 100;
				col[24] = FormatChange(changeS, 2);
				col[25] = FormatChange(changeV, 2);
				col[27] = FormatChange(changeT, 2);
				col[28] = FormatChange(changeR, 2);
				col[30] = FormatFloat(changeIV, 1);
			}

			col[9] = FormatFloat(ivol*100, 1);
			if (GreeksIn == 0)
			{
				col[10] = FormatFloat(delta, 2);
				col[11] = FormatFloat(gamma, 2);
			}
			else
			{
				col[10] = FormatFloat(delta, 1);
				col[11] = FormatFloat(gamma, 1);
			}
			col[12] = FormatFloat(vega, 2);
			col[13] = FormatFloat(rho, 2);
			col[14] = FormatFloat(theta, 2);
			col[20] = FormatFloat(probIM, 2);
			col[22] = moe < 0 ? "" : FormatFloat(moe, 2);
			col[23] = delta2theta == "N" ? "" : FormatFloat(delta2theta, 2);
		}

		// Put
		flag = record[11].substring(EndPoint, EndPoint+1);
		ticker = record[12];
		last = record[13];
		bid = record[14] == "N" ? -1 : parseFloat(record[14]);
		ask = record[15] == "N" ? -1 : parseFloat(record[15]);
		bid0 = record[16] == "N" ? -1 : parseFloat(record[16]);
		ask0 = record[17] == "N" ? -1 : parseFloat(record[17]);
		volume = record[18] == "N" ? -1 : parseInt(record[18]);
		open = record[19] == "N" ? -1 : parseInt(record[19]);
		open0 = record[20] == "N" ? -1 : parseInt(record[20]);

		mid = -1, mid0 = -1;
		if (bid >= 0 && ask >= 0)
			mid = (bid + ask) / 2;
		if (bid0 >= 0 && ask0 >= 0)
			mid0 = (bid0 + ask0) / 2;

		change = "N";
		if ((EndPoint == 0) && mid0 >= 0 && mid >= 0)
			change = mid - mid0;
		else if ((EndPoint == 1) && bid0 >= 0 && bid >= 0)
			change = bid - bid0;
		else if ((EndPoint == 2) && ask0 >= 0 && ask >= 0)
			change = ask - ask0;

		changeOpen = "N";
		if (open >= 0 && open0 >= 0)
			changeOpen = open - open0;

		oprice = -1;
		if (flag == "N")
		{
			if (EndPoint == 0 && mid >= 0)
				oprice = mid;
			else if (EndPoint == 1 && bid >= 0)
				oprice = bid;
			else if (EndPoint == 2 && ask >= 0)
				oprice = ask;
		}

		intValue = Math.max(strike-lastPrice, 0);
		timeValue = oprice < 0 ? -1 : oprice - intValue;
		annPrem = oprice < 0 ? -1 : 100 * Math.log(1 + oprice / strike) / exptime;
		annTime = timeValue < 0 ? -1 : 100 * Math.log(1 + timeValue / strike) / exptime;
		breakEven = oprice < 0 ? -200 : ((strike - oprice) / lastPrice - 1) * 100;

		col[1+NP] = flag == "N" ? "" : flag;
		col[2+NP] = ticker;
		col[3+NP] = last == "N" ? "N/A" : last;
		col[4+NP] = change == "N" ? "N/A" : FormatChange(change, 2);
		col[5+NP] = bid < 0 ? "N/A" : FormatFloat(bid, 2);
		col[6+NP] = ask < 0 ? "N/A" : FormatFloat(ask, 2);
		col[7+NP] = volume < 0 ? "N/A" : FormatLong(volume);
		col[8+NP] = open < 0 ? "N/A" : FormatLong(open);
		col[15+NP] = FormatFloat(money, 0);
		col[16+NP] = FormatFloat(intValue, 2);
		col[17+NP] = timeValue < 0 ? "" : FormatFloat(timeValue, 2);
		col[18+NP] = annPrem < 0 ? "" : FormatFloat(annPrem, 2);
		col[19+NP] = annTime < 0 ? "" : FormatFloat(annTime, 2);
		col[21+NP] = breakEven < -100 ? "" : FormatFloat(breakEven, 2);
		col[26+NP] = changeOpen == "N" ? "N/A" : FormatLong(changeOpen);
		col[29+NP] = mid < 0 ? "N/A" : FormatFloat(mid, 2);

		ivol = -1;
		if (oprice > 0)
			ivol = IV(lastPrice, strike, exptime, irate, yield, 1, oprice);

		if (ivol > 0)
		{
			var d1 = (du + ivol * ivol * exptime / 2) / (ivol * st);
			var d2 = d1 - ivol * st;
			var Nd1 = NormDist(-d1);
			var Nd2 = NormDist(-d2);
			var nd1 = Math.exp(-0.5 * d1 * d1) / spi;

			var delta = -eqt * Nd1;
			var gamma = nd1 * eqt / (lastPrice * ivol * st);
			var vega = p1 * st * nd1 / 100;
			var rho = -exptime * x1 * Nd2 / 100;
			var theta = (-p1 * nd1 * ivol / (2 * st) - yield * p1 * Nd1 + irate * x1 * Nd2) / 365;
			var probIM = NormDist(-(Math.log(lastPrice/(strike-oprice)) + (irate-yield-ivol*ivol/2)*exptime) / (ivol*st)) * 100;
			var moe = -1;
			if (mid > 0)
				moe = (bid - ask) * 100 * oprice / (mid * delta * lastPrice);
			if (GreeksIn == 1)
			{
				gamma *= lastPrice / delta;
				delta *= lastPrice / oprice;
				vega *= ivol * 100 / oprice;
				rho *= 100 / oprice;
				theta *= 100 / oprice;
			}
			var delta2theta = "N";
			if (theta != 0)
				delta2theta = delta / theta;

			var oprice0 = -1;
			if (flag == "N")
			{
				if (EndPoint == 0 && mid0 >= 0)
					oprice0 = mid0;
				else if (EndPoint == 1 && bid0 >= 0)
					oprice0 = bid0;
				else if (EndPoint == 2 && ask0 >= 0)
					oprice0 = ask0;
			}

			var ivol0 = -1;
			if (oprice0 > 0)
				ivol0 = IV(closePrice, strike, exptime0, irate, yield, 1, oprice0);
			if (ivol0 > 0)
			{
				var changeS = OptionPrice(lastPrice, strike, exptime0, ivol0, irate, yield, 1) - oprice0;
				var changeV = OptionPrice(closePrice, strike, exptime0, ivol, irate, yield, 1) - oprice0;
				var changeT = OptionPrice(closePrice, strike, exptime, ivol0, irate, yield, 1) - oprice0;
				var changeR = oprice - oprice0 - changeS - changeV - changeT;
				var changeIV = (ivol - ivol0) * 100;
				col[24+NP] = FormatChange(changeS, 2);
				col[25+NP] = FormatChange(changeV, 2);
				col[27+NP] = FormatChange(changeT, 2);
				col[28+NP] = FormatChange(changeR, 2);
				col[30+NP] = FormatFloat(changeIV, 1);
			}

			col[9+NP] = FormatFloat(ivol*100, 1);
			if (GreeksIn == 0)
			{
				col[10+NP] = FormatFloat(delta, 2);
				col[11+NP] = FormatFloat(gamma, 2);
			}
			else
			{
				col[10+NP] = FormatFloat(delta, 1);
				col[11+NP] = FormatFloat(gamma, 1);
			}
			col[12+NP] = FormatFloat(vega, 2);
			col[13+NP] = FormatFloat(rho, 2);
			col[14+NP] = FormatFloat(theta, 2);
			col[20+NP] = FormatFloat(probIM, 2);
			col[22+NP] = moe < 0 ? "" : FormatFloat(moe, 2);
			col[23+NP] = delta2theta == "N" ? "" : FormatFloat(delta2theta, 2);
		}

		row[j] = col.join("^");
	}
	return row.join("|");
}

function CalATables1(id, bv)
{
	var exptime = (chnDaysToExpire[id] + 1) / 365;
	var exptime0 = (chnDaysToExpire[id] + day2Close + 1) / 365;
	var irate = chnRate[id] / 100;
	var yield = chnYield[id] / 100;
	var st = Math.sqrt(exptime);
	var p1 = lastPrice * Math.exp(-yield * exptime);
	var eqt = Math.exp(-yield * exptime);
	var ert = Math.exp(-irate * exptime);
	var spi = Math.sqrt(2 * Math.PI);

	var options = chnOptions[id].split("|");
	var row = new Array();

	for (var j = 0; j < options.length; j++)
	{
		var record = options[j].split(",");
		var col = new Array(NUMCOL*2+5);

		var strike = parseFloat(record[0]);
		col[0] = FormatFloat(strike, 2);

		var du = Math.log(lastPrice/strike) + (irate-yield) * exptime;
		var x1 = strike * Math.exp(-irate * exptime);

		var flagc = record[1].substring(EndPoint, EndPoint+1);
		var flagp = record[11].substring(EndPoint, EndPoint+1);
		var tickerc = record[2];
		var tickerp = record[12];
		var flag = flagc + flagp;
		col[1] = flag == "NN" ? "" : flag;
		col[2] = tickerc + " / " + tickerp;

		var bidc = record[4] == "N" ? -1 : parseFloat(record[4]);
		var askc = record[5] == "N" ? -1 : parseFloat(record[5]);
		var bid0c = record[6] == "N" ? -1 : parseFloat(record[6]);
		var ask0c = record[7] == "N" ? -1 : parseFloat(record[7]);
		var bidp = record[14] == "N" ? -1 : parseFloat(record[14]);
		var askp = record[15] == "N" ? -1 : parseFloat(record[15]);
		var bid0p = record[16] == "N" ? -1 : parseFloat(record[16]);
		var ask0p = record[17] == "N" ? -1 : parseFloat(record[17]);

		var bid = "N", ask = "N";
		if (bidc >= 0 && askp >= 0)
			bid = bidc - askp;
		if (askc >= 0 && bidp >= 0)
			ask = askc - bidp;

		var bid0 = "N", ask0 = "N";
		if (bid0c >= 0 && ask0p >= 0)
			bid0 = bid0c - ask0p;
		if (ask0c >= 0 && bid0p >= 0)
			ask0 = ask0c - bid0p;

		var mid = "N", mid0 = "N";
		if (bid != "N" && ask != "N")
			mid = (bid + ask) / 2;
		if (bid0 != "N" && ask0 != "N")
			mid0 = (bid0 + ask0) / 2;

		var change = "N";
		if ((EndPoint == 0) && mid0 != "N" && mid != "N")
			change = mid - mid0;
		else if ((EndPoint == 1) && bid0 != "N" && bid != "N")
			change = bid - bid0;
		else if ((EndPoint == 2) && ask0 != "N" && ask != "N")
			change = ask - ask0;

		var oprice = "N", opricec = "N", opricep = "N";
		if (flag == "NN")
		{
			if (EndPoint == 0 && mid != "N")
			{
				oprice = mid;
				opricec = (bidc + askc) / 2;
				opricep = (bidp + askp) / 2;
			}
			else if (EndPoint == 1 && bid != "N")
			{
				oprice = bid;
				opricec = bidc;
				opricep = askp;
			}
			else if (EndPoint == 2 && ask != "N")
			{
				oprice = ask;
				opricec = askc;
				opricep = bidp;
			}
		}

		var money = 100 * strike / lastPrice;
		var intValue = lastPrice;
		var timeValue = oprice == "N" ? "N" : oprice - intValue + strike;
		var annPrem = oprice == "N" ? "N" : 100 * Math.log((oprice + strike) / lastPrice) / exptime;
		var annTime = timeValue == "N" ? "N" : 100 * Math.log(1 + timeValue / strike) / exptime;

		col[4] = change == "N" ? "N/A" : FormatChange(change, 2);
		col[5] = bid == "N" ? "N/A" : FormatFloat(bid, 2);
		col[6] = ask == "N" ? "N/A" : FormatFloat(ask, 2);
		col[15] = FormatFloat(money, 0);
		col[16] = FormatFloat(intValue, 2);
		col[17] = timeValue == "N" ? "" : FormatFloat(timeValue, 2);
		col[18] = annPrem == "N" ? "" : FormatFloat(annPrem, 2);
		col[19] = annTime == "N" ? "" : FormatFloat(annTime, 2);
		col[29] = mid == "N" ? "N/A" : FormatFloat(mid, 2);

		var ivolc = -1, ivolp = -1;
		if (opricec != "N" && opricep != "N")
		{
			ivolc = IV(lastPrice, strike, exptime, irate, yield, 0, opricec);
			ivolp = IV(lastPrice, strike, exptime, irate, yield, 1, opricep);
		}

		if (ivolc > 0 && ivolp > 0)
		{
			var d1c = (du + ivolc * ivolc * exptime / 2) / (ivolc * st);
			var d2c = d1c - ivolc * st;
			var Nd1c = NormDist(d1c);
			var Nd2c = NormDist(d2c);
			var nd1c = Math.exp(-0.5 * d1c * d1c) / spi;

			var d1p = (du + ivolp * ivolp * exptime / 2) / (ivolp * st);
			var d2p = d1p - ivolp * st;
			var Nd1p = NormDist(-d1p);
			var Nd2p = NormDist(-d2p);
			var nd1p = Math.exp(-0.5 * d1p * d1p) / spi;

			var deltac = eqt * Nd1c;
//			var gammac = nd1c * eqt / (lastPrice * ivolc * st);
//			var vegac = p1 * st * nd1c / 100;
//			var rhoc = exptime * x1 * Nd2c / 100;
//			var thetac = (-p1 * nd1c * ivolc / (2 * st) + yield * p1 * Nd1c - irate * x1 * Nd2c) / 365;

			var deltap = -eqt * Nd1p;
//			var gammap = nd1p * eqt / (lastPrice * ivolp * st);
//			var vegap = p1 * st * nd1p / 100;
//			var rhop = -exptime * x1 * Nd2p / 100;
//			var thetap = (-p1 * nd1p * ivolp / (2 * st) - yield * p1 * Nd1p + irate * x1 * Nd2p) / 365;

			var delta = deltac - deltap;
//			var gamma = gammac - gammap;
//			var vega = vegac - vegap;
//			var rho = rhoc - rhop;
//			var theta =  thetac - thetap;
			var moe = "N";
			if (mid != "N")
				moe = (ask - bid) * 100 * oprice / (mid * delta * lastPrice);
			if (GreeksIn == 1)
			{
				delta *= lastPrice / oprice;
			}

			var oprice0 = "N", oprice0c = "N", oprice0p = "N";
			if (flag == "NN")
			{
				if (EndPoint == 0 && mid0 != "N")
				{
					oprice0 = mid0;
					oprice0c = (bid0c + ask0c) / 2;
					oprice0p = (bid0p + ask0p) / 2;
				}
				else if (EndPoint == 1 && bid0 != "N")
				{
					oprice0 = bid0;
					oprice0c = bid0c;
					oprice0p = ask0p;
				}
				else if (EndPoint == 2 && ask0 != "N")
				{
					oprice0 = ask0;
					oprice0c = ask0c;
					oprice0p = bid0p;
				}
			}

			var ivol0c = -1, ivol0p = -1;
			if (oprice0c != "N" && oprice0p != "N")
			{
				ivol0c = IV(closePrice, strike, exptime0, irate, yield, 0, oprice0c);
				ivol0p = IV(closePrice, strike, exptime0, irate, yield, 1, oprice0p);

				if (ivol0c > 0 && ivol0p > 0)
				{
					var changeS = OptionPrice(lastPrice, strike, exptime0, ivol0c, irate, yield, 0)
								- OptionPrice(lastPrice, strike, exptime0, ivol0p, irate, yield, 1)
								- oprice0;
					var changeV = OptionPrice(closePrice, strike, exptime0, ivolc, irate, yield, 0)
								- OptionPrice(closePrice, strike, exptime0, ivolp, irate, yield, 1)
								- oprice0;
					var changeT = OptionPrice(closePrice, strike, exptime, ivol0c, irate, yield, 0)
								- OptionPrice(closePrice, strike, exptime, ivol0p, irate, yield, 1)
								- oprice0;
					var changeR = oprice - oprice0 - changeS - changeV - changeT;
					col[24] = FormatChange(changeS, 2);
					col[25] = FormatChange(changeV, 2);
					col[27] = FormatChange(changeT, 2);
					col[28] = FormatChange(changeR, 2);
				}
			}

			if (GreeksIn == 0)
				col[10] = FormatFloat(delta, 2);
			else
				col[10] = FormatFloat(delta, 1);
//			col[11] = FormatFloat(gamma, 2);
//			col[12] = FormatFloat(vega, 2);
//			col[13] = FormatFloat(rho, 2);
//			col[14] = FormatFloat(theta, 2);
			col[22] = moe == "N" ? "" : FormatFloat(moe, 2);
		}

		row[j] = col.join("^");
	}

	return row.join("|");
}

function CalATables2(id, bv)
{
	var ii = GetChain2(id);
	if (ii == -1 || chnOptions[ii] == "")
		return "";

	var offset = 10;
	var NP = NUMCOL + 2;
	var exptime = new Array(2);
	var exptime0 = new Array(2);
	var irate = new Array(2);
	var yield = new Array(2);
	var st = new Array(2);
	var p1 = new Array(2);
	var eqt = new Array(2);
	var ert = new Array(2);
	exptime[0] = (chnDaysToExpire[id] + 1) / 365;
	exptime[1] = (chnDaysToExpire[ii] + 1) / 365;
	exptime0[0] = (chnDaysToExpire[id] + day2Close + 1) / 365;
	exptime0[1] = (chnDaysToExpire[ii] + day2Close + 1) / 365;
	var exptimemin = Math.min(exptime[0], exptime[1]);
	irate[0] = chnRate[id] / 100;
	irate[1] = chnRate[ii] / 100;
	yield[0] = chnYield[id] / 100;
	yield[1] = chnYield[ii] / 100;
	st[0] = Math.sqrt(exptime[0]);
	st[1] = Math.sqrt(exptime[1]);
	p1[0] = lastPrice * Math.exp(-yield[0] * exptime[0]);
	p1[1] = lastPrice * Math.exp(-yield[1] * exptime[1]);
	eqt[0] = Math.exp(-yield[0] * exptime[0]);
	eqt[1] = Math.exp(-yield[1] * exptime[1]);
	ert[0] = Math.exp(-irate[0] * exptime[0]);
	ert[1] = Math.exp(-irate[1] * exptime[1]);
	var spi = Math.sqrt(2 * Math.PI);

	var options = chnOptions[id].split("|");
	var row = new Array();

	for (var j = 0, k = 0; j < options.length; j++)
	{
		var record = options[j].split(",");
		var strike = parseFloat(record[0]);

		// Call
		var flag = record[1].substring(EndPoint, EndPoint+1);
		var ticker = record[2];
		var bid = record[4] == "N" ? -1 : parseFloat(record[4]);
		var ask = record[5] == "N" ? -1 : parseFloat(record[5]);
		var bid0 = record[6] == "N" ? -1 : parseFloat(record[6]);
		var ask0 = record[7] == "N" ? -1 : parseFloat(record[7]);

		var option2 = GetOption2(ii, strike, 0, flag);
		if (option2 == null)
			continue;

		// Option1 is long (higher ask) and option2 is short (lower ask). Switch the position if the other way.
		var option1, idx1, idx2;
		if (ask >= option2.ask)
		{
			option1 = new OptionObj(ticker, flag, strike, bid, ask, bid0, ask0);
			idx1 = 0;
			idx2 = 1;
		}
		else
		{
			option1 = new OptionObj(option2.ticker, option2.flag, option2.strike, option2.bid, option2.ask, option2.bid0, option2.ask0);
			option2 = new OptionObj(ticker, flag, strike, bid, ask, bid0, ask0);
			idx1 = 1;
			idx2 = 0;
		}

		var du1 = Math.log(lastPrice/option1.strike) + (irate[idx1]-yield[idx1]) * exptime[idx1];
		var du2 = Math.log(lastPrice/option2.strike) + (irate[idx2]-yield[idx2]) * exptime[idx2];
		var x11 = option1.strike * Math.exp(-irate[idx1] * exptime[idx1]);
		var x12 = option2.strike * Math.exp(-irate[idx2] * exptime[idx2]);

		var col = new Array(NUMCOL*2+5);
		if (option1.strike == option2.strike)
			col[0] = FormatFloat(option1.strike, 2);
		else if (option1.strike < option2.strike)
			col[0] = FormatFloat(option1.strike, 2) + "/" + FormatFloat(option2.strike, 2);
		else
			col[0] = FormatFloat(option2.strike, 2) + "/" + FormatFloat(option1.strike, 2);

		ticker = option1.ticker + " / " + option2.ticker;
		flag = option1.flag + option2.flag;
		col[1] = flag == "NN" ? "" : flag;
		col[2] = ticker;

		bid = ask = bid0 = ask0 = "N";
		if (option1.bid >= 0 && option2.ask >= 0)
			bid = option1.bid - option2.ask;
		if (option1.ask >= 0 && option2.bid >= 0)
			ask = option1.ask - option2.bid;
		if (option1.bid0 >= 0 && option2.ask0 >= 0)
			bid0 = option1.bid0 - option2.ask0;
		if (option1.ask0 >= 0 && option2.bid0 >= 0)
			ask0 = option1.ask0 - option2.bid0;

		var mid = "N", mid0 = "N";
		if (bid != "N" && ask != "N")
			mid = (bid + ask) / 2;
		if (bid0 != "N" && ask0 != "N")
			mid0 = (bid0 + ask0) / 2;

		var change = "N";
		if ((EndPoint == 0) && mid0 != "N" && mid != "N")
			change = mid - mid0;
		else if ((EndPoint == 1) && bid0 != "N" && bid != "N")
			change = bid - bid0;
		else if ((EndPoint == 2) && ask0 != "N" && ask != "N")
			change = ask - ask0;

		var oprice = "N", oprice1 = "N", oprice2 = "N";
		if (flag == "NN")
		{
			if (EndPoint == 0 && mid != "N")
			{
				oprice = mid;
				oprice1 = (option1.bid + option1.ask) / 2;
				oprice2 = (option2.bid + option2.ask) / 2;
			}
			else if (EndPoint == 1 && bid != "N")
			{
				oprice = bid;
				oprice1 = option1.bid;
				oprice2 = option2.ask;
			}
			else if (EndPoint == 2 && ask != "N")
			{
				oprice = ask;
				oprice1 = option1.ask;
				oprice2 = option2.bid;
			}
		}

		var strike0 = (option1.strike + option2.strike) / 2;
		var money = 100 * strike0 / lastPrice;
		var intValue = Math.max(lastPrice-option1.strike, 0) - Math.max(lastPrice-option2.strike, 0);
		var timeValue = oprice == "N" ? "N" : oprice - intValue;
		var annPrem = oprice == "N" ? "N" : 100 * Math.log(1 + oprice / strike0) / exptimemin;
		var annTime = timeValue == "N" ? "N" : 100 * Math.log(1 + timeValue / strike0) / exptimemin;
		var impOdd = "N";
		if (TableType == 2)
			impOdd = oprice == "N" ? "N" : 100 * oprice / (option2.strike - option1.strike);
/* sjin next
		var breakEven = -200;
		if (oprice != "N")
		{
			if (option2.strike > option1.strike && option1.ask > option2.ask && (option2.strike - option1.strike) >= oprice)
				breakEven = ((option1.strike + oprice) / lastPrice - 1) * 100;
		}
*/

		col[4] = change == "N" ? "N/A" : FormatChange(change, 2);
		col[5] = bid == "N" ? "N/A" : FormatFloat(bid, 2);
		col[6] = ask == "N" ? "N/A" : FormatFloat(ask, 2);
		col[15] = FormatFloat(money, 0);
		col[16] = FormatFloat(intValue, 2);
		col[17] = timeValue == "N" ? "" : FormatFloat(timeValue, 2);
		col[18] = annPrem == "N" ? "" : FormatFloat(annPrem, 2);
		col[19] = annTime == "N" ? "" : FormatFloat(annTime, 2);
//		col[21] = breakEven < -100 ? "" : FormatFloat(breakEven, 2);
		col[29] = mid == "N" ? "N/A" : FormatFloat(mid, 2);
		col[31] = impOdd == "N" ? "" : FormatFloat(impOdd, 2);

		var ivol1 = -1, ivol2 = -1;
		if (oprice1 != "N" && oprice2 != "N")
		{
			ivol1 = IV(lastPrice, option1.strike, exptime[idx1], irate[idx1], yield[idx1], 0, oprice1);
			ivol2 = IV(lastPrice, option2.strike, exptime[idx2], irate[idx2], yield[idx2], 0, oprice2);
		}

		if (ivol1 > 0 && ivol2 > 0)
		{
			var d11 = (du1 + ivol1 * ivol1 * exptime[idx1] / 2) / (ivol1 * st[idx1]);
			var d12 = (du2 + ivol2 * ivol2 * exptime[idx2] / 2) / (ivol2 * st[idx2]);
			var d21 = d11 - ivol1 * st[idx1];
			var d22 = d12 - ivol2 * st[idx2];
			var Nd11 = NormDist(d11);
			var Nd12 = NormDist(d12);
			var Nd21 = NormDist(d21);
			var Nd22 = NormDist(d22);
			var nd11 = Math.exp(-0.5 * d11 * d11) / spi;
			var nd12 = Math.exp(-0.5 * d12 * d12) / spi;

			var delta = eqt[idx1] * Nd11 - eqt[idx2] * Nd12;
			var gamma = nd11 * eqt[idx1] / (lastPrice * ivol1 * st[idx1]) - nd12 * eqt[idx2] / (lastPrice * ivol2 * st[idx2]);
			var vega = p1[idx1] * st[idx1] * nd11 / 100 - p1[idx2] * st[idx2] * nd12 / 100;
			var rho = exptime[idx1] * x11 * Nd21 / 100 - exptime[idx2] * x12 * Nd22 / 100;
			var theta = (-p1[idx1] * nd11 * ivol1 / (2 * st[idx1]) + yield[idx1] * p1[idx1] * Nd11 - irate[idx1] * x11 * Nd21) / 365 - (-p1[idx2] * nd12 * ivol2 / (2 * st[idx2]) + yield[idx2] * p1[idx2] * Nd12 - irate[idx2] * x12 * Nd22) / 365;
			var moe = "N";
			if (mid > 0)
				moe = Math.abs((ask - bid) * 100 * oprice / (mid * delta * lastPrice));
			var delta2theta = "N";
			if (theta != 0)
				delta2theta = delta / theta;
			if (GreeksIn == 1)
			{
				gamma *= lastPrice / delta;
				delta *= lastPrice / oprice;
				vega *= ((OptionPrice(lastPrice, option1.strike, exptime[idx1], ivol1*1.01, irate[idx1], yield[idx1], 0)
					  - OptionPrice(lastPrice, option2.strike, exptime[idx2], ivol2*1.01, irate[idx2], yield[idx2], 0))
					  / oprice - 1) * 100;
				rho *= 100 / oprice;
				theta *= 100 / oprice;
			}

			var oprice0 = "N", oprice01 = "N", oprice02 = "N";
			if (flag == "NN")
			{
				if (EndPoint == 0 && mid0 != "N")
				{
					oprice0 = mid0;
					oprice01 = (option1.bid0 + option1.ask0) / 2;
					oprice02 = (option2.bid0 + option2.ask0) / 2;
				}
				else if (EndPoint == 1 && bid0 != "N")
				{
					oprice0 = bid0;
					oprice01 = option1.bid0;
					oprice02 = option2.ask0;
				}
				else if (EndPoint == 2 && ask0 != "N")
				{
					oprice0 = ask0;
					oprice01 = option1.ask0;
					oprice02 = option2.bid0;
				}
			}

			var ivol01 = -1, ivol02 = -1;
			if (oprice01 != "N" && oprice02 != "N")
			{
				ivol01 = IV(closePrice, option1.strike, exptime0[idx1], irate[idx1], yield[idx1], 0, oprice01);
				ivol02 = IV(closePrice, option2.strike, exptime0[idx2], irate[idx2], yield[idx2], 0, oprice02);

				if (ivol01 > 0 && ivol02 > 0)
				{
					var changeS = OptionPrice(lastPrice, option1.strike, exptime0[idx1], ivol01, irate[idx1], yield[idx1], 0)
								- OptionPrice(lastPrice, option2.strike, exptime0[idx2], ivol02, irate[idx2], yield[idx2], 0)
								- oprice0;
					var changeV = OptionPrice(closePrice, option1.strike, exptime0[idx1], ivol1, irate[idx1], yield[idx1], 0)
								- OptionPrice(closePrice, option2.strike, exptime0[idx2], ivol2, irate[idx2], yield[idx2], 0)
								- oprice0;
					var changeT = OptionPrice(closePrice, option1.strike, exptime[idx1], ivol01, irate[idx1], yield[idx1], 0)
								- OptionPrice(closePrice, option2.strike, exptime[idx2], ivol02, irate[idx2], yield[idx2], 0)
								- oprice0;
					var changeR = oprice - oprice0 - changeS - changeV - changeT;
					col[24] = FormatChange(changeS, 2);
					col[25] = FormatChange(changeV, 2);
					col[27] = FormatChange(changeT, 2);
					col[28] = FormatChange(changeR, 2);
				}
			}

			if (GreeksIn == 0)
			{
				col[10] = FormatFloat(delta, 2);
				col[11] = FormatFloat(gamma, 2);
			}
			else
			{
				col[10] = FormatFloat(delta, 1);
				col[11] = FormatFloat(gamma, 1);
			}
			col[12] = FormatFloat(vega, 2);
			col[13] = FormatFloat(rho, 2);
			col[14] = FormatFloat(theta, 2);
			col[22] = moe == "N" ? "" : FormatFloat(moe, 2);
			col[23] = delta2theta == "N" ? "" : FormatFloat(delta2theta, 2);
		}

		// Put
		flag = record[11].substring(EndPoint, EndPoint+1);
		ticker = record[12];
		bid = record[14] == "N" ? -1 : parseFloat(record[14]);
		ask = record[15] == "N" ? -1 : parseFloat(record[15]);
		bid0 = record[16] == "N" ? -1 : parseFloat(record[16]);
		ask0 = record[17] == "N" ? -1 : parseFloat(record[17]);

		option2 = GetOption2(ii, strike, offset, flag);

		if (ask >= option2.ask)
		{
			option1 = new OptionObj(ticker, flag, strike, bid, ask, bid0, ask0);
			idx1 = 0;
			idx2 = 1;
		}
		else
		{
			option1 = new OptionObj(option2.ticker, option2.flag, option2.strike, option2.bid, option2.ask, option2.bid0, option2.ask0);
			option2 = new OptionObj(ticker, flag, strike, bid, ask, bid0, ask0);
			idx1 = 1;
			idx2 = 0;
		}

		du1 = Math.log(lastPrice/option1.strike) + (irate[idx1]-yield[idx1]) * exptime[idx1];
		du2 = Math.log(lastPrice/option2.strike) + (irate[idx2]-yield[idx2]) * exptime[idx2];
		x11 = option1.strike * Math.exp(-irate[idx1] * exptime[idx1]);
		x12 = option2.strike * Math.exp(-irate[idx2] * exptime[idx2]);

		ticker = option1.ticker + " / " + option2.ticker;
		flag = option1.flag + option2.flag;
		col[1+NP] = flag == "NN" ? "" : flag;
		col[2+NP] = ticker;

		bid = ask = bid0 = ask0 = "N";
		if (option1.bid >= 0 && option2.ask >= 0)
			bid = option1.bid - option2.ask;
		if (option1.ask >= 0 && option2.bid >= 0)
			ask = option1.ask - option2.bid;
		if (option1.bid0 >= 0 && option2.ask0 >= 0)
			bid0 = option1.bid0 - option2.ask0;
		if (option1.ask0 >= 0 && option2.bid0 >= 0)
			ask0 = option1.ask0 - option2.bid0;

		mid = "N", mid0 = "N";
		if (bid != "N" && ask != "N")
			mid = (bid + ask) / 2;
		if (bid0 != "N" && ask0 != "N")
			mid0 = (bid0 + ask0) / 2;

		change = "N";
		if ((EndPoint == 0) && mid0 != "N" && mid != "N")
			change = mid - mid0;
		else if ((EndPoint == 1) && bid0 != "N" && bid != "N")
			change = bid - bid0;
		else if ((EndPoint == 2) && ask0 != "N" && ask != "N")
			change = ask - ask0;

		oprice = "N", oprice1 = "N", oprice2 = "N";
		if (flag == "NN")
		{
			if (EndPoint == 0 && mid != "N")
			{
				oprice = mid;
				oprice1 = (option1.bid + option1.ask) / 2;
				oprice2 = (option2.bid + option2.ask) / 2;
			}
			else if (EndPoint == 1 && bid != "N")
			{
				oprice = bid;
				oprice1 = option1.bid;
				oprice2 = option2.ask;
			}
			else if (EndPoint == 2 && ask != "N")
			{
				oprice = ask;
				oprice1 = option1.ask;
				oprice2 = option2.bid;
			}
		}

		strike0 = (option1.strike + option2.strike) / 2;
		money = 100 * strike0 / lastPrice;
		intValue = Math.max(option1.strike-lastPrice, 0) - Math.max(option2.strike-lastPrice, 0);
		timeValue = oprice == "N" ? "N" : oprice - intValue;
		annPrem = oprice == "N" ? "N" : 100 * Math.log(1 + oprice / strike0) / exptimemin;;
		annTime = timeValue == "N" ? "N" : 100 * Math.log(1 + timeValue / strike0) / exptimemin;
		impOdd = "N";
		if (TableType == 2)
			impOdd = oprice == "N" ? "N" : 100 * oprice / (option1.strike - option2.strike);
/* sjin next
		breakEven = -200;
		if (oprice != "N")
		{
			if (option2.strike > option1.strike && option2.ask > option1.ask && (option2.strike - option1.strike) >= oprice)
				breakEven = ((option2.strike - oprice) / lastPrice - 1) * 100;
		}
*/

		col[4+NP] = change == "N" ? "N/A" : FormatChange(change, 2);
		col[5+NP] = bid == "N" ? "N/A" : FormatFloat(bid, 2);
		col[6+NP] = ask == "N" ? "N/A" : FormatFloat(ask, 2);
		col[15+NP] = FormatFloat(money, 0);
		col[16+NP] = FormatFloat(intValue, 2);
		col[17+NP] = timeValue == "N" ? "" : FormatFloat(timeValue, 2);
		col[18+NP] = annPrem == "N" ? "" : FormatFloat(annPrem, 2);
		col[19+NP] = annTime == "N" ? "" : FormatFloat(annTime, 2);
//		col[21+NP] = breakEven < -100 ? "" : FormatFloat(breakEven, 2);
		col[29+NP] = mid == "N" ? "N/A" : FormatFloat(mid, 2);
		col[31+NP] = impOdd == "N" ? "" : FormatFloat(impOdd, 2);

		ivol1 = ivol2 = -1;
		if (oprice1 != "N" && oprice2 != "N")
		{
			ivol1 = IV(lastPrice, option1.strike, exptime[idx1], irate[idx1], yield[idx1], 1, oprice1);
			ivol2 = IV(lastPrice, option2.strike, exptime[idx2], irate[idx2], yield[idx2], 1, oprice2);
		}

		if (ivol1 > 0 && ivol2 > 0)
		{
			var d11 = (du1 + ivol1 * ivol1 * exptime[idx1] / 2) / (ivol1 * st[idx1]);
			var d12 = (du2 + ivol2 * ivol2 * exptime[idx2] / 2) / (ivol2 * st[idx2]);
			var d21 = d11 - ivol1 * st[idx1];
			var d22 = d12 - ivol2 * st[idx2];
			var Nd11 = NormDist(-d11);
			var Nd12 = NormDist(-d12);
			var Nd21 = NormDist(-d21);
			var Nd22 = NormDist(-d22);
			var nd11 = Math.exp(-0.5 * d11 * d11) / spi;
			var nd12 = Math.exp(-0.5 * d12 * d12) / spi;

			var delta = -eqt[idx1] * Nd11 + eqt[idx2] * Nd12;
			var gamma = nd11 * eqt[idx1] / (lastPrice * ivol1 * st[idx1]) - nd12 * eqt[idx2] / (lastPrice * ivol2 * st[idx2]);
			var vega = p1[idx1] * st[idx1] * nd11 / 100 - p1[idx2] * st[idx2] * nd12 / 100;
			var rho = -exptime[idx1] * x11 * Nd21 / 100 + exptime[idx2] * x12 * Nd22 / 100;
			var theta = (-p1[idx1] * nd11 * ivol1 / (2 * st[idx1]) - yield[idx1] * p1[idx1] * Nd11 + irate[idx1] * x11 * Nd21) / 365 - (-p1[idx2] * nd12 * ivol2 / (2 * st[idx2]) - yield[idx2] * p1[idx2] * Nd12 + irate[idx2] * x12 * Nd22) / 365;
			var moe = "N";
			if (mid > 0)
				moe = Math.abs((ask - bid) * 100 * oprice / (mid * delta * lastPrice));
			var delta2theta = "N";
			if (theta != 0)
				delta2theta = delta / theta;
			if (GreeksIn == 1)
			{
				gamma *= lastPrice / delta;
				delta *= lastPrice / oprice;
				vega *= ((OptionPrice(lastPrice, option1.strike, exptime[idx1], ivol1*1.01, irate[idx1], yield[idx1], 1)
					  - OptionPrice(lastPrice, option2.strike, exptime[idx2], ivol2*1.01, irate[idx2], yield[idx2], 1))
					  / oprice - 1) * 100;
				rho *= 100 / oprice;
				theta *= 100 / oprice;
			}

			oprice0 = oprice01 = oprice02 = "N";
			if (flag == "NN")
			{
				if (EndPoint == 0 && mid0 != "N")
				{
					oprice0 = mid0;
					oprice01 = (option1.bid0 + option1.ask0) / 2;
					oprice02 = (option2.bid0 + option2.ask0) / 2;
				}
				else if (EndPoint == 1 && bid0 != "N")
				{
					oprice0 = bid0;
					oprice01 = option1.bid0;
					oprice02 = option2.ask0;
				}
				else if (EndPoint == 2 && ask0 != "N")
				{
					oprice0 = ask0;
					oprice01 = option1.ask0;
					oprice02 = option2.bid0;
				}
			}

			ivol01 = ivol02 = -1;
			if (oprice01 != "N" && oprice02 != "N")
			{
				ivol01 = IV(closePrice, option1.strike, exptime0[idx1], irate[idx1], yield[idx1], 1, oprice01);
				ivol02 = IV(closePrice, option2.strike, exptime0[idx2], irate[idx2], yield[idx2], 1, oprice02);

				if (ivol01 > 0 && ivol02 > 0)
				{
					var changeS = OptionPrice(lastPrice, option1.strike, exptime0[idx1], ivol01, irate[idx1], yield[idx1], 1)
								- OptionPrice(lastPrice, option2.strike, exptime0[idx2], ivol02, irate[idx2], yield[idx2], 1)
								- oprice0;
					var changeV = OptionPrice(closePrice, option1.strike, exptime0[idx1], ivol1, irate[idx1], yield[idx1], 1)
								- OptionPrice(closePrice, option2.strike, exptime0[idx2], ivol2, irate[idx2], yield[idx2], 1)
								- oprice0;
					var changeT = OptionPrice(closePrice, option1.strike, exptime[idx1], ivol01, irate[idx1], yield[idx1], 1)
								- OptionPrice(closePrice, option2.strike, exptime[idx2], ivol02, irate[idx2], yield[idx2], 1)
								- oprice0;
					var changeR = oprice - oprice0 - changeS - changeV - changeT;
					col[24+NP] = FormatChange(changeS, 2);
					col[25+NP] = FormatChange(changeV, 2);
					col[27+NP] = FormatChange(changeT, 2);
					col[28+NP] = FormatChange(changeR, 2);
				}
			}

			if (GreeksIn == 0)
			{
				col[10+NP] = FormatFloat(delta, 2);
				col[11+NP] = FormatFloat(gamma, 2);
			}
			else
			{
				col[10+NP] = FormatFloat(delta, 1);
				col[11+NP] = FormatFloat(gamma, 1);
			}
			col[12+NP] = FormatFloat(vega, 2);
			col[13+NP] = FormatFloat(rho, 2);
			col[14+NP] = FormatFloat(theta, 2);
			col[22+NP] = moe == "N" ? "" : FormatFloat(moe, 2);
			col[23+NP] = delta2theta == "N" ? "" : FormatFloat(delta2theta, 2);
		}

		row[k++] = col.join("^");
	}

	return row.join("|");
}

//////////////////////////////////////////////////
// Utilities
// Get 2nd chain ID for table header bar
function GetChain2(id)
{
	if (TableType == 3 || TableType == 4)
	{
		var id2 = id + TimeStep;
		if (id2 >= NCHN)
			id2 = -1;
		return id2;
	}

	return id;
}

// Get 2nd option for spread
function GetOption2(i, x, o, f)
{
	var x2 = x;
	if (TableType == 2 || TableType == 4)
		x2 += chnSpace[i] * StrikeStep;

	var options = chnOptions[i].split("|");
	for (var j = 0; j < options.length; j++)
	{
		var record = options[j].split(",");
		var flag = record[1+o].substring(EndPoint, EndPoint+1);
		if (f == "N" || f == "o")
		{
			if (flag != "N" && flag != "o")
				continue;
		}
		else
		{
			if (flag == "N" || flag == "o")
				continue;
		}

		var strike = parseFloat(record[0]);
		if (strike != x2)
			continue;

		var ticker = record[2+o];
		var bid = record[4+o] == "N" ? -1 : parseFloat(record[4+o]);
		var ask = record[5+o] == "N" ? -1 : parseFloat(record[5+o]);
		var bid0 = record[6+o] == "N" ? -1 : parseFloat(record[6+o]);
		var ask0 = record[7+o] == "N" ? -1 : parseFloat(record[7+o]);
		return new OptionObj(ticker, flag, x2, bid, ask, bid0, ask0);
	}
	return null;
}

function FormatFloat(v, d)
{
	var sign = v < 0 ? -1: 1;
	var vv = Math.abs(v);
	var power = Math.pow(10, d);
	vv = vv * power + 0.00000001;
	vv = sign * Math.round(vv) / power;
	return vv.toFixed(d);
}

function FormatChange(v, d)
{
	var vv = Math.abs(v);
	if (vv > 10000)
		return "N/A";

	var power = Math.pow(10, d);
	vv = vv * power + 0.00000001;
	vv = Math.round(vv) / power;
	vv = vv.toFixed(d);

	var prefix, aftfix, vvDef = "0.00";
	if (vv == vvDef)
	{
		prefix = "";
		aftfix = "";
	}
	else if (v < 0)
	{
		prefix = "<img src='http://im.morningstar.com/im/arrowdown1.gif'><img src='http://im.morningstar.com/im/dot_clear.gif' width=2 height=7><span class=ColorDown>";
		aftfix = "</span>";
	}
	else if (v > 0)
	{
		prefix = "<img src='http://im.morningstar.com/im/arrowup1.gif'><img src='http://im.morningstar.com/im/dot_clear.gif' width=2 height=7><span class=ColorUp>";
		aftfix = "</span>";
	}

	return prefix + vv + aftfix;
}

function FormatLong(v)
{
	var sign = v < 0 ? "-": "";
	v = Math.abs(v);
	v += "";
	var s = "", r = "", len = v.length;
	while (len > 3)
	{
		r = v.substring(len-3);
		v = v.substring(0, len-3);
		s = "," + r + s;
		len = v.length;
	}
	s = sign + v + s;
	return s;
}

function IV(s, x, t, r, q, tt, p)
{
	var e = 0.0001, n = 13;
	var pLim = Math.min(0.005, 0.01 * p);

	var v = Math.sqrt(Math.abs(Math.log(s/x) + (r-q)*t) * 2 / t);
	if (v <= 0)
		v = 0.1;
	var c = OptionPrice(s, x, t, v, r, q, tt);
	if (Math.abs(p - c) < pLim)
		return v;

	var vega = Vega(s, x, t, v, r, q);
	var v1 = v - (c - p) / vega;
	var step = 1;
	while (Math.abs(v - v1) > e && step < n)
	{
		v = v1;
		c = OptionPrice(s, x, t, v, r, q, tt);
		if (Math.abs(p - c) < pLim)
			return v;
		vega = Vega(s, x, t, v, r, q);
		v1 = v - (c - p) / vega;
		if (v1 < 0)
			return v1;
		step++;
	}
	if (step < n)
		return v1;

	c = OptionPrice(s, x, t, v1, r, q, tt);
	if (Math.abs(p - c) < pLim)
		return v1;
	else
		return -1;
}

function IV2(s, x1, t1, r1, q1, x2, t2, r2, q2, tt, p)
{
	var e = 0.0001, n = 13;
	var pLim = Math.min(0.005, 0.01 * p);

	var v = Math.sqrt(Math.abs(Math.log(s/x1) + (r1-q1)*t1) * 2 / t1);
	if (v <= 0)
		v = 0.1;
	var c = OptionPrice(s, x1, t1, v, r1, q1, tt) - OptionPrice(s, x2, t2, v, r2, q2, tt);
	if (Math.abs(p - c) < pLim)
		return v;

	var vega = Vega(s, x1, t1, v, r1, q1) - Vega(s, x2, t2, v, r2, q2);
	var v1 = v - (c - p) / vega;
	var step = 1;
	while (Math.abs(v - v1) > e && step < n)
	{
		v = v1;
		c = OptionPrice(s, x1, t1, v, r1, q1, tt) - OptionPrice(s, x2, t2, v, r2, q2, tt);
		if (Math.abs(p - c) < pLim)
			return v;
		vega = Vega(s, x1, t1, v, r1, q1) - Vega(s, x2, t2, v, r2, q2);
		v1 = v - (c - p) / vega;
		if (v1 < 0)
			return v1;
		step++;
	}
	if (step < n)
		return v1;

	c = OptionPrice(s, x1, t1, v, r1, q1, tt) - OptionPrice(s, x2, t2, v, r2, q2, tt)
	if (Math.abs(p - c) < pLim)
		return v1;
	else
		return -1;
}

function Vega(s, x, t, v, r, q)
{
	var st = Math.sqrt(t);
	var du = Math.log(s/x) + (r-q) * t;
	var p1 = s * Math.exp(-q * t);
	var d1 = (du + v * v * t / 2) / (v * st);
	var nd = Math.exp(-d1 * d1 / 2) / Math.sqrt(2 * Math.PI);
	return p1 * st * nd;
}

function OptionPrice(s, x, t, v, r, q, tt)
{
	var st = Math.sqrt(t);
	var du = Math.log(s/x) + (r-q) * t;
	var p1 = s * Math.exp(-q * t);
	var x1 = x * Math.exp(-r * t);
	var d1 = (du + v * v * t / 2) / (v * st);
	var d2 = d1 - v * st;
	if (tt == 0)
		return p1 * NormDist(d1) - x1 * NormDist(d2);
	else
		return x1 * NormDist(-d2) - p1 * NormDist(-d1);
}

function NormDist(x)
{
	var p  =  0.2316419;
	var b1 =  0.319381530;
	var b2 = -0.356563782;
	var b3 =  1.781477937;
	var b4 = -1.821255978;
	var b5 =  1.330274429;
	
	var y = Math.abs(x);
	var z = Math.exp(-y*y/2) / Math.sqrt(2 * Math.PI);
	var t = 1 / ( 1 + p * y);
	var cum = 1 - z * (b1*t + b2*t*t + b3*t*t*t + b4*t*t*t*t + b5*t*t*t*t*t);
	if (x < 0)
		cum = 1 - cum;
	return cum;
}

function OptionObj(ticker, flag, strike, bid, ask, bid0, ask0)
{
	this.ticker = ticker;
	this.flag = flag;
	this.strike = strike;
	this.bid = bid;
	this.ask = ask;
	this.bid0 = bid0;
	this.ask0 = ask0;
}

