Natural Gas Price Monitor

Natural Gas Price Monitor 🔥

  • 1. NatGas Futures Specs
  • 2. My NatGas Positions
  • 3. Tracking Summary

Natural Gas Futures Contract Specifications (NYMEX NG)

My Natural Gas Positions (Manual Input)

Tracking Summary & Resources

Overall Portfolio P&L:

Total Unrealized P&L: $0.00


Tracked Positions Details:

No positions tracked yet, or P&L not calculated.

Total Unrealized P&L: N/A

`; if (NGPM_trackedPositionsContainer) NGPM_trackedPositionsContainer.appendChild(entryDiv); if(positionId === 1 && document.getElementById(`ngpm-positionDesc-${positionId}`).value === "") { document.getElementById(`ngpm-positionDesc-${positionId}`).value = "NYMEX NG Futures"; document.getElementById(`ngpm-quantity-${positionId}`).value = "1"; } } function NGPM_removeTrackedPosition(positionId) { const entryDiv = document.getElementById(`ngpm-position-entry-${positionId}`); if (entryDiv && NGPM_trackedPositionsContainer) { NGPM_trackedPositionsContainer.removeChild(entryDiv); } NGPM_updatePortfolioSummary(); } function NGPM_calculatePnLSingle(positionId, fromPortfolioUpdate = false) { const unitTypeEl = document.getElementById(`ngpm-unitType-${positionId}`); const quantityEl = document.getElementById(`ngpm-quantity-${positionId}`); const entryPriceEl = document.getElementById(`ngpm-entryPrice-${positionId}`); const currentPriceEl = document.getElementById(`ngpm-currentPrice-${positionId}`); const pnlDetailsDiv = document.getElementById(`ngpm-pnlDetails-${positionId}`); if (!unitTypeEl || !quantityEl || !entryPriceEl || !currentPriceEl || !pnlDetailsDiv) { if(pnlDetailsDiv) pnlDetailsDiv.innerHTML = "

Error: Missing input fields for this entry.

"; return 0; } const unitType = unitTypeEl.value; const quantity = parseFloat(quantityEl.value); const entryPrice = parseFloat(entryPriceEl.value); const currentPrice = parseFloat(currentPriceEl.value); if (isNaN(quantity) || isNaN(entryPrice) || isNaN(currentPrice) || quantity === 0) { pnlDetailsDiv.innerHTML = `

Price Change per Unit: N/A

Total Unrealized P&L: N/A

`; if (!fromPortfolioUpdate) NGPM_updatePortfolioSummary(); return 0; } const priceChangePerUnit = currentPrice - entryPrice; let totalPnl = 0; if (unitType === "Futures Contracts") { const spec = NGPM_NATGAS_SPEC_DATA; if (quantity > 0) { // Long totalPnl = (priceChangePerUnit / spec.tickSize) * spec.tickValue * quantity; } else { // Short totalPnl = ((entryPrice - currentPrice) / spec.tickSize) * spec.tickValue * Math.abs(quantity); } } else { // MMBtu (custom), Other - simple P&L totalPnl = priceChangePerUnit * quantity; } // Determine number of decimal places for priceChange based on tickSize, if it's a future let priceChangeDecimals = 2; // Default if (unitType === "Futures Contracts") { const tickStr = NGPM_NATGAS_SPEC_DATA.tickSize.toString(); priceChangeDecimals = tickStr.includes('.') ? tickStr.split('.')[1].length : 0; } pnlDetailsDiv.innerHTML = `

Price Change per Unit: ${NGPM_formatCurrency(priceChangePerUnit)}

Total Unrealized P&L: ${NGPM_formatCurrency(totalPnl)}

`; if (!fromPortfolioUpdate) NGPM_updatePortfolioSummary(); return totalPnl; } function NGPM_updatePortfolioSummary() { if (!NGPM_trackedPositionsContainer || !NGPM_totalPortfolioPnlSpan || !NGPM_trackedPositionsSummaryTableContainer) return; let overallTotalPnl = 0; const positionEntries = NGPM_trackedPositionsContainer.querySelectorAll('.ngpm-tracked-position-entry'); let tableHTML = ``; if (positionEntries.length === 0) { NGPM_trackedPositionsSummaryTableContainer.innerHTML = "

No positions currently being tracked.

"; NGPM_totalPortfolioPnlSpan.textContent = NGPM_formatCurrency(0); return; } positionEntries.forEach(entry => { const positionId = entry.id.split('-').pop(); const currentPnlForThisPosition = NGPM_calculatePnLSingle(positionId, true); overallTotalPnl += currentPnlForThisPosition; const desc = document.getElementById(`ngpm-positionDesc-${positionId}`)?.value || "N/A"; const entryDate = document.getElementById(`ngpm-entryDate-${positionId}`)?.value || "N/A"; const quantity = parseFloat(document.getElementById(`ngpm-quantity-${positionId}`)?.value) || 0; const unitType = document.getElementById(`ngpm-unitType-${positionId}`)?.value || "N/A"; const entryPrice = parseFloat(document.getElementById(`ngpm-entryPrice-${positionId}`)?.value) || 0; const currentPrice = parseFloat(document.getElementById(`ngpm-currentPrice-${positionId}`)?.value) || 0; const pnlClass = currentPnlForThisPosition >= 0 ? 'ngpm-profit' : 'ngpm-loss'; let entryPriceDisplay = isNaN(entryPrice) ? "N/A" : NGPM_formatCurrency(entryPrice); let currentPriceDisplay = isNaN(currentPrice) ? "N/A" : NGPM_formatCurrency(currentPrice); if (unitType === "Futures Contracts" || unitType === "MMBtu") { // More decimals for MMBtu typically entryPriceDisplay = isNaN(entryPrice) ? "N/A" : entryPrice.toFixed(3); currentPriceDisplay = isNaN(currentPrice) ? "N/A" : currentPrice.toFixed(3); } tableHTML += ``; }); tableHTML += `
Description Entry Date Qty Unit Entry Price Current Price Total P&L
${desc} ${entryDate} ${quantity} ${unitType} ${entryPriceDisplay} ${currentPriceDisplay} ${NGPM_formatCurrency(currentPnlForThisPosition)}
`; NGPM_trackedPositionsSummaryTableContainer.innerHTML = tableHTML; NGPM_totalPortfolioPnlSpan.className = overallTotalPnl >= 0 ? 'ngpm-profit' : 'ngpm-loss'; NGPM_totalPortfolioPnlSpan.textContent = NGPM_formatCurrency(overallTotalPnl); } function NGPM_updateAllPnLsAndNavigate(targetTabId) { NGPM_updatePortfolioSummary(); NGPM_navigateToTab(targetTabId); } async function NGPM_generatePDF() { if (!NGPM_portfolioSummaryOutput || !NGPM_pdfSpecificTitle) { console.error("NGPM: PDF export content area not found."); alert("Error: Could not generate PDF. Content area missing."); return; } NGPM_updatePortfolioSummary(); const positionEntries = NGPM_trackedPositionsContainer ? NGPM_trackedPositionsContainer.querySelectorAll('.ngpm-tracked-position-entry') : []; if (positionEntries.length === 0) { alert("Please add and track at least one position to generate a report."); return; } NGPM_pdfSpecificTitle.style.display = 'block'; const originalToolTitle = document.querySelector('.ngpm-tool-title'); if (originalToolTitle) originalToolTitle.style.display = 'none'; const pdfContentArea = document.getElementById('ngpm-pdfExportContent'); const originalBg = pdfContentArea.style.backgroundColor; pdfContentArea.style.backgroundColor = '#ffffff'; try { const canvas = await html2canvas(pdfContentArea, { scale: 1.5, useCORS: true, backgroundColor: '#ffffff', windowWidth: pdfContentArea.scrollWidth, windowHeight: pdfContentArea.scrollHeight }); const imgData = canvas.toDataURL('image/png'); const pdf = new jsPDF({ orientation: 'p', unit: 'mm', format: 'a4' }); const pdfWidth = pdf.internal.pageSize.getWidth(); const pdfHeight = pdf.internal.pageSize.getHeight(); const imgProps = pdf.getImageProperties(imgData); const imgRatio = imgProps.width / imgProps.height; let newImgWidth = pdfWidth - 20; let newImgHeight = newImgWidth / imgRatio; let positionY = 10; if (newImgHeight > pdfHeight - 20) { const pageCanvas = document.createElement('canvas'); pageCanvas.width = canvas.width; const A4_PX_HEIGHT = (pdfHeight - 20) * (canvas.width / newImgWidth); pageCanvas.height = A4_PX_HEIGHT; const pageCtx = pageCanvas.getContext('2d'); let srcY = 0; while(srcY < canvas.height) { const srcHeight = Math.min(A4_PX_HEIGHT, canvas.height - srcY); pageCanvas.height = srcHeight; pageCtx.clearRect(0, 0, pageCanvas.width, pageCanvas.height); pageCtx.drawImage(canvas, 0, srcY, canvas.width, srcHeight, 0, 0, canvas.width, srcHeight); const pageImgData = pageCanvas.toDataURL('image/png'); // const pageImgProps = pdf.getImageProperties(pageImgData); // Not strictly needed if dimensions are calculated // const pageImgRatio = pageImgProps.width / pageImgProps.height; let pageFinalWidth = pdfWidth - 20; let pageFinalHeight = pageFinalWidth / (canvas.width / srcHeight); // Use original aspect for the slice if (srcY > 0) pdf.addPage(); pdf.addImage(pageImgData, 'PNG', 10, positionY, pageFinalWidth, pageFinalHeight); srcY += srcHeight; } } else { const x = (pdfWidth - newImgWidth) / 2; pdf.addImage(imgData, 'PNG', x, positionY, newImgWidth, newImgHeight); } pdf.save('Natural_Gas_Positions_Monitor_Summary.pdf'); } catch (error) { console.error("Error generating PDF:", error); alert("An error occurred while generating the PDF: " + error.message); } finally { NGPM_pdfSpecificTitle.style.display = 'none'; if (originalToolTitle) originalToolTitle.style.display = 'block'; pdfContentArea.style.backgroundColor = originalBg; } } document.addEventListener('DOMContentLoaded', function() { NGPM_initDOMElements(); if (!NGPM_tabs || !NGPM_tabContents) { console.error("NGPM: Tool initialization failed."); const container = document.getElementById('ngpmToolContainer'); if(container) container.innerHTML = "

Error: Tool components failed to load.

"; return; } NGPM_tabs.forEach(tab => { tab.addEventListener('click', function() { if (this.dataset && this.dataset.tab) { NGPM_navigateToTab(this.dataset.tab); } }); }); NGPM_displayNatGasSpecs(); NGPM_addTrackedPositionFields(); NGPM_updatePortfolioSummary(); NGPM_navigateToTab('ngpm-tab1'); });
Scroll to Top