Educational Real Estate Market Cycle Indicator

A self-assessment tool to help you think about market phases based on your observations.

** VERY IMPORTANT - PLEASE READ **
  • This tool is for educational and illustrative purposes ONLY. It is a self-assessment framework.
  • Market timing is extremely difficult. Real estate markets are hyper-local and influenced by many complex factors.
  • The "suggested phase" is based on generalized theory and **your subjective inputs** for the indicators. It is **NOT a prediction or financial advice.**
  • Indicators can be mixed in real-world scenarios, and this tool uses a simplified logic.
  • **Always conduct thorough local market research and consult with qualified real estate professionals and financial advisors** before making any decisions.

Assess Current Market Indicators (Based on your research for a specific market)

${phaseDisplayName}

`; let detailsHtml = `
Typical Characteristics of ${phaseDisplayName}:
    `; phaseInfo.characteristics.forEach(char => detailsHtml += `
  • ${char}
  • `); detailsHtml += `
`; if(phaseInfo.considerations && phaseInfo.considerations.length > 0){ detailsHtml += `
General Considerations for ${phaseDisplayName}:
    `; phaseInfo.considerations.forEach(con => detailsHtml += `
  • ${con}
  • `); detailsHtml += `
`; } this.elements.phaseDetailsDisplay.innerHTML = detailsHtml; this.elements.resultsSection.style.display = 'block'; this.results = { // Store for PDF suggestedPhaseKey, phaseDisplayName, inputs: this.userInputs, characteristics: phaseInfo.characteristics, considerations: phaseInfo.considerations }; }, determineMarketPhase: function(inputs) { // Simplified rule-based logic. More complex weighting or scoring could be used. // This is highly illustrative and will have limitations. const { priceTrend, salesVolume, inventoryLevels, newConstruction, vacancyRateRental, daysOnMarket } = inputs; // Recession indicators (strongest signals first) if ((priceTrend === 'rapid_decrease' || priceTrend === 'moderate_decrease') && (inventoryLevels === 'very_high' || inventoryLevels === 'high') && (salesVolume === 'low' || salesVolume === 'decreasing') && (newConstruction === 'minimal' || newConstruction === 'decreasing_stalled') && (vacancyRateRental === 'high' || vacancyRateRental === 'increasing') && (daysOnMarket === 'long' || daysOnMarket === 'increasing')) { return 'Recession'; } // Hyper Supply indicators if ((priceTrend === 'stable' || priceTrend === 'moderate_decrease') && (inventoryLevels === 'high' || inventoryLevels === 'increasing') && (newConstruction === 'high_stable' || newConstruction === 'decreasing_stalled') && (vacancyRateRental === 'increasing') && (salesVolume === 'decreasing' || salesVolume === 'high_stable')) { return 'HyperSupply'; } // Expansion indicators if ((priceTrend === 'rapid_increase' || priceTrend === 'moderate_increase') && (inventoryLevels === 'very_low' || inventoryLevels === 'low') && (salesVolume === 'high_increasing' || salesVolume === 'high_stable') && (newConstruction === 'high_increasing' || newConstruction === 'high_stable') && (vacancyRateRental === 'low_decreasing' || vacancyRateRental === 'low_stable') && (daysOnMarket === 'short_decreasing' || daysOnMarket === 'short_stable')) { return 'Expansion'; } // Recovery indicators if ((priceTrend === 'moderate_increase' || priceTrend === 'stable') && (inventoryLevels === 'low' || inventoryLevels === 'balanced' || inventoryLevels === 'decreasing') && (salesVolume === 'increasing' || salesVolume === 'low') && (newConstruction === 'minimal' || newConstruction === 'increasing') && (vacancyRateRental === 'low_decreasing' || vacancyRateRental === 'decreasing' || vacancyRateRental === 'low_stable') && (daysOnMarket === 'decreasing' || daysOnMarket === 'short_stable')) { return 'Recovery'; } // Default to Mixed Signals if no strong pattern matches return 'MixedSignals'; }, generatePDF: async function() { if (!window.jspdf || !window.html2canvas || !this.results || !this.results.suggestedPhaseKey) { alert('Please analyze the market phase first to generate a PDF.'); return; } await new Promise(resolve => setTimeout(resolve, 50)); const r = this.results; const pdfExportContainer = document.createElement('div'); pdfExportContainer.classList.add('mct-pdf-export-content'); pdfExportContainer.style.width = '800px'; let pdfHtml = `

Real Estate Market Cycle Assessment

`; pdfHtml += `
** IMPORTANT REMINDER **
This assessment is based on YOUR subjective inputs and generalized market cycle theory. It is for educational/illustrative purposes ONLY and is NOT financial or investment advice. Real estate is local and complex. Consult qualified professionals.
`; pdfHtml += `

Your Market Indicator Selections

`; for(const key in r.inputs){ const labelElement = document.querySelector(`label[for="${key}"]`); const selectElement = this.elements[key]; const labelText = labelElement ? labelElement.textContent.replace(':','') : key; const selectedOptionText = selectElement ? Array.from(selectElement.options).find(opt => opt.value === r.inputs[key])?.text : r.inputs[key]; pdfHtml += `
${labelText}: ${selectedOptionText || 'N/A'}
`; } pdfHtml += `
`; pdfHtml += `

Suggested Market Phase (Based on Your Inputs)

`; pdfHtml += `
${r.phaseDisplayName}
`; pdfHtml += `

Typical Characteristics of ${r.phaseDisplayName}

    `; r.characteristics.forEach(char => pdfHtml += `
  • ${char}
  • `); pdfHtml += `
`; if (r.considerations && r.considerations.length > 0) { pdfHtml += `

General Considerations for ${r.phaseDisplayName}

    `; r.considerations.forEach(con => pdfHtml += `
  • ${con}
  • `); pdfHtml += `
`; } pdfExportContainer.innerHTML = pdfHtml; document.body.appendChild(pdfExportContainer); try { const canvas = await html2canvas(pdfExportContainer, { scale: 1.5, useCORS: true, logging: false, windowWidth: pdfExportContainer.scrollWidth }); document.body.removeChild(pdfExportContainer); const imgData = canvas.toDataURL('image/png'); const { jsPDF } = window.jspdf; const pdf = new jsPDF({ orientation: 'p', unit: 'pt', format: 'a4' }); const pdfWidth = pdf.internal.pageSize.getWidth(); const pdfHeight = pdf.internal.pageSize.getHeight(); const imgProps = pdf.getImageProperties(imgData); let imgFinalWidth = pdfWidth - 40; let imgFinalHeight = (imgProps.height * imgFinalWidth) / imgProps.width; if (imgFinalHeight > pdfHeight - 40) { imgFinalHeight = pdfHeight - 40; imgFinalWidth = (imgProps.width * imgFinalHeight) / imgProps.height; } let currentY = 20; let heightProcessed = 0; const pageMargin = 20; const pageHeightAvailable = pdfHeight - 2 * pageMargin; while(heightProcessed < canvas.height) { let pageSegmentHeightOnCanvas = Math.min(canvas.height - heightProcessed, (pageHeightAvailable / imgFinalHeight) * canvas.height ); if (pageSegmentHeightOnCanvas <=0) break; const segmentCanvas = document.createElement('canvas'); segmentCanvas.width = canvas.width; segmentCanvas.height = pageSegmentHeightOnCanvas; const sctx = segmentCanvas.getContext('2d'); sctx.drawImage(canvas, 0, heightProcessed, canvas.width, pageSegmentHeightOnCanvas, 0, 0, canvas.width, pageSegmentHeightOnCanvas); const segmentImgData = segmentCanvas.toDataURL('image/png'); const segmentImgPropsPdf = pdf.getImageProperties(segmentImgData); let segmentRenderWidth = pdfWidth - 2 * pageMargin; let segmentRenderHeight = (segmentImgPropsPdf.height * segmentRenderWidth) / segmentImgPropsPdf.width; if(segmentRenderHeight > pageHeightAvailable) { segmentRenderHeight = pageHeightAvailable; segmentRenderWidth = (segmentImgPropsPdf.width * segmentRenderHeight) / segmentImgPropsPdf.height; } if(heightProcessed > 0) pdf.addPage(); pdf.addImage(segmentImgData, 'PNG', pageMargin, pageMargin, segmentRenderWidth, segmentRenderHeight); heightProcessed += pageSegmentHeightOnCanvas; } pdf.save('Real_Estate_Market_Cycle_Assessment.pdf'); } catch (error) { console.error("Error generating PDF:", error); alert("An error occurred while generating PDF."); if (document.body.contains(pdfExportContainer)) document.body.removeChild(pdfExportContainer); } } }; document.addEventListener('DOMContentLoaded', function() { mctApp.init(); });
Scroll to Top