Do any of the SFREP users know if Appraise-It Pro has a Weighted Average feature for the sales approach reconciliation?
ACI and Alamode do.
I know this post is years old and I don't know if Appraise-It does it natively now, but I saw this post and thought it would be fun to try and get a script developed that will calculate a weighted average. The weights are based on gross/net adjustments (lower get more weight supposedly). No guarantees as to the accuracy and i'm no expert in the way this works but it appears to produce credible results in an addendum and the code looks legit. It also demonstrates the possibilities of being able to interact with appraisal software with such a generous and an open API.
Anway, here is the Lua script. Just copy and save it to notebook, save as Whatever.LUA so you can access it from Tools----->Script------>Whatever.
(I named mine Weighted Average.LUA).
-- Script Begin
-- Replace 'YourComparableType' with the actual comparable type you want to work with. (SaleComparables, ListingComparables, Rental Comparables)
local comparableType = 'SalesComparables'
-- Function to get the requested adjustment for a comparable
function GetAdjustment(compIndex, adjustmentName)
local adjustmentText = Pro.TextField(comparableType, compIndex, adjustmentName).Text
local adjustmentValue = tonumber(adjustmentText) or 0
return adjustmentValue
end
-- Function to calculate the weighted average of adjusted sale prices
function CalculateWeightedAverage()
local totalWeightedSalePrice = 0
local totalWeight = 0
local numComparables = Pro.GetCompCount(comparableType)
local lowestGrossAdjustmentComp, lowestNetAdjustmentComp
local lowestGrossAdjustment = math.huge
local lowestNetAdjustment = math.huge
-- Details for all comparables
local allComparablesDetails = {}
for i = 1, numComparables do
local grossAdjustment = GetAdjustment(i, "GrossAdjustmentPercentage")
local netAdjustment = GetAdjustment(i, "NetAdjustmentPercentage")
local adjustedSalePrice = GetAdjustment(i, "AdjustedSalePriceAmount")
-- Find comparables with the lowest gross and net adjustments
if grossAdjustment < lowestGrossAdjustment then
lowestGrossAdjustment = grossAdjustment
lowestGrossAdjustmentComp = i
end
if netAdjustment < lowestNetAdjustment then
lowestNetAdjustment = netAdjustment
lowestNetAdjustmentComp = i
end
-- Calculate the weight for the comparable
local weight = 1 / (grossAdjustment + netAdjustment + 1) -- Adding 1 to avoid division by zero
-- Accumulate the total weighted sale price
totalWeightedSalePrice = totalWeightedSalePrice + (adjustedSalePrice * weight)
totalWeight = totalWeight + weight
-- Store details for all comparables
table.insert(allComparablesDetails, {
ComparableIndex = i,
GrossAdjustment = grossAdjustment,
NetAdjustment = netAdjustment,
AdjustedSalePrice = adjustedSalePrice,
Weight = weight
})
end
-- Calculate the weighted average
local weightedAverage = totalWeightedSalePrice / totalWeight
return weightedAverage, lowestGrossAdjustmentComp, lowestNetAdjustmentComp, allComparablesDetails
end
-- Temporary variable to store the combined text
local combinedText = ""
-- Function to add text to the addendum
function addToAddendum(text)
combinedText = combinedText .. text .. "\n"
end
-- Calculate the weighted average of adjusted sale prices
local weightedAverage, lowestGrossAdjustmentComp, lowestNetAdjustmentComp, allComparablesDetails = CalculateWeightedAverage()
-- Output the result to the addendum
addToAddendum(string.format("Weighted Average Based on Gross/Net Adjustments of Comparable Adjusted Sale Prices: $%.2f", weightedAverage))
addToAddendum("\nSummary:")
addToAddendum(string.format("Comparable with lowest gross adjustment: Comparable #%d (Gross Adjustment: %.2f%%)", lowestGrossAdjustmentComp, GetAdjustment(lowestGrossAdjustmentComp, "GrossAdjustmentPercentage")))
addToAddendum(string.format("Comparable with lowest net adjustment: Comparable #%d (Net Adjustment: %.2f%%)", lowestNetAdjustmentComp, GetAdjustment(lowestNetAdjustmentComp, "NetAdjustmentPercentage")))
-- Add details for the comparables with the lowest adjustments
addToAddendum("\nDetails for Comparables with Lowest Adjustments:")
addToAddendum("--------------------------------------------------")
-- Comparable with lowest gross adjustment
addToAddendum(string.format("Comparable #%d:", lowestGrossAdjustmentComp))
addToAddendum(string.format("Gross Adjustment: %.2f%%", GetAdjustment(lowestGrossAdjustmentComp, "GrossAdjustmentPercentage")))
addToAddendum(string.format("Net Adjustment: %.2f%%", GetAdjustment(lowestGrossAdjustmentComp, "NetAdjustmentPercentage")))
addToAddendum(string.format("Adjusted Sale Price: $%.2f", GetAdjustment(lowestGrossAdjustmentComp, "AdjustedSalePriceAmount")))
addToAddendum("-------------------------------")
-- Comparable with lowest net adjustment
addToAddendum(string.format("Comparable #%d:", lowestNetAdjustmentComp))
addToAddendum(string.format("Gross Adjustment: %.2f%%", GetAdjustment(lowestNetAdjustmentComp, "GrossAdjustmentPercentage")))
addToAddendum(string.format("Net Adjustment: %.2f%%", GetAdjustment(lowestNetAdjustmentComp, "NetAdjustmentPercentage")))
addToAddendum(string.format("Adjusted Sale Price: $%.2f", GetAdjustment(lowestNetAdjustmentComp, "AdjustedSalePriceAmount")))
addToAddendum("-------------------------------")
-- Add details for all comparables
addToAddendum("\nDetails for All Comparables:")
addToAddendum("--------------------------------------------------")
for _, comparableDetails in ipairs(allComparablesDetails) do
addToAddendum(string.format("Comparable #%d:", comparableDetails.ComparableIndex))
addToAddendum(string.format("Gross Adjustment: %.2f%%", comparableDetails.GrossAdjustment))
addToAddendum(string.format("Net Adjustment: %.2f%%", comparableDetails.NetAdjustment))
addToAddendum(string.format("Adjusted Sale Price: $%.2f", comparableDetails.AdjustedSalePrice))
addToAddendum(string.format("Weight: %.4f", comparableDetails.Weight))
addToAddendum("-------------------------------")
end
-- Write the combined text to a temporary file
local filePath = os.tmpname()
local file = io.open(filePath, 'w')
file:write(combinedText)
file:close()
-- Add the file contents to a word processing addendum
local useFormWithHeader = true
Pro.InsertWordProcessingDocument(useFormWithHeader, filePath)
-- Delete the temporary file
os.remove(filePath)