Skip to main content

Portfolio Analysis

This use case shows how to query and analyze property portfolio data within a geographic area using shapes, filters, and accumulation.

Using Python?

The Python SDK wraps all portfolio endpoints in a typed client — client.reports_v1.points_selection(...), client.reports_v1.accumulation_selection(...), etc.

Scenario

You have a real estate portfolio and need to:

  1. Get available data sources and filters
  2. Define a geographic area of interest
  3. Query properties and entries within that area
  4. Aggregate metrics (count, sum, average) by column

Step 1: Discover Available Data

First, understand what data and filters are available:

curl -X GET "https://graph.quarticle.ro/graph/api/v1/reports/portfolio/provision?source=portfolio_01" \
-H "Authorization: YOUR_API_KEY"

Response:

{
"provisioning": {
"portfolio_01": {
"columns": [
{ "field": "property_id", "type": "string" },
{ "field": "name", "type": "string" },
{ "field": "value", "type": "number" },
{ "field": "occupancy_rate", "type": "number" },
{ "field": "year_built", "type": "string" },
{ "field": "property_type", "type": "string" }
],
"filters": [
{
"field": "oe_id",
"label": "Organization",
"required": true,
"values": ["chicago_portfolio", "nyc_portfolio"]
},
{
"field": "property_type",
"label": "Property Type",
"required": false,
"values": ["residential", "office", "retail", "industrial"]
}
],
"points": {
"cluster": {
"attributes": [
{ "field": "value", "label": "Total Value", "aggregation": "sum" }
]
}
},
"reports": {
"accumulation": {
"enabled": true,
"fields": [
{ "field": "value", "label": "Insured Value", "default": true },
{ "field": "occupancy_rate", "label": "Occupancy Rate" }
]
}
}
}
}
}

Use this response to discover available columns for entries queries, filters and their allowed values, and which reports are enabled for the source.

You can also retrieve just the filter hierarchy:

curl -X GET "https://graph.quarticle.ro/graph/api/v1/reports/portfolio/provision/filters" \
-H "Authorization: YOUR_API_KEY"

Step 2: Get Points in a Geographic Area

Define your area of interest as a GeoJSON polygon, then query for points:

{
"source": "portfolio_01",
"shape": {
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [[
[-87.6500, 41.8000],
[-87.5500, 41.8000],
[-87.5500, 41.9000],
[-87.6500, 41.9000],
[-87.6500, 41.8000]
]]
},
"properties": {}
},
"filters": [
{"field": "oe_id", "value": "chicago_portfolio"}
],
"properties": ["name", "address", "value", "property_type"]
}

Response:

[
{
"type": "Feature",
"properties": {
"name": "Downtown Office Tower",
"address": "100 N LaSalle, Chicago, IL",
"value": 850000000,
"property_type": "office"
},
"geometry": {"type": "Point", "coordinates": [-87.6301, 41.8857]}
},
{
"type": "Feature",
"properties": {
"name": "Residential Complex",
"address": "500 N Dearborn, Chicago, IL",
"value": 425000000,
"property_type": "residential"
},
"geometry": {"type": "Point", "coordinates": [-87.6220, 41.8886]}
}
]

Step 3: Get Detailed Entries in Area

For detailed records (not just points), use entries endpoint:

{
"source": "portfolio_01",
"shape": {
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [[
[-87.6500, 41.8000],
[-87.5500, 41.8000],
[-87.5500, 41.9000],
[-87.6500, 41.9000],
[-87.6500, 41.8000]
]]
},
"properties": {}
},
"filters": [{"field": "oe_id", "value": "chicago_portfolio"}],
"columns": ["property_id", "name", "value", "occupancy_rate", "year_built"],
"limit": 100,
"page": 0
}

Export as CSV by adding Accept: text/csv header.

Step 4: Accumulate Metrics

Aggregate data across the area using accumulation:

{
"source": "portfolio_01",
"shape": {
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [[
[-87.6500, 41.8000],
[-87.5500, 41.8000],
[-87.5500, 41.9000],
[-87.6500, 41.9000],
[-87.6500, 41.8000]
]]
},
"properties": {}
},
"filters": [{"field": "oe_id", "value": "chicago_portfolio"}],
"aggregationColumns": ["value", "occupancy_rate"],
"locale": "en-US"
}

Response:

[
{
"analysis": {
"count": 47,
"value": {
"sum": 12500000000,
"avg": 265957446,
"min": 2000000,
"max": 850000000
},
"occupancy_rate": {
"avg": 0.852,
"min": 0.65,
"max": 0.99
}
},
"radius": null
}
]

Step 5: Multi-Radius Buffer Analysis

Analyze data at multiple distances from a center point:

{
"source": "portfolio_01",
"shape": {
"type": "circle",
"coordinates": [{ "lat": 41.8857, "long": -87.6298 }]
},
"radiuses": [1000, 5000, 10000],
"filters": [{"field": "oe_id", "value": "chicago_portfolio"}],
"aggregationColumns": ["value", "occupancy_rate"]
}

Response shows results for each radius:

[
{
"analysis": {...},
"radius": 1000
},
{
"analysis": {...},
"radius": 5000
},
{
"analysis": {...},
"radius": 10000
}
]

Complete Workflow (JavaScript)

async function portfolioAnalysis() {
const apiKey = process.env.QARTA_API_KEY;
const source = 'portfolio_01';

// Step 1: Get provision info
const provision = await fetch(
`https://graph.quarticle.ro/graph/api/v1/reports/portfolio/provision?source=${source}`,
{ headers: { 'Authorization': `${apiKey}` } }
).then(r => r.json());

console.log('Available columns:', provision.provisioning[source].columns.map(c => c.field));

// Define area (downtown Chicago)
const area = {
type: "Feature",
geometry: {
type: "Polygon",
coordinates: [[
[-87.6500, 41.8000],
[-87.5500, 41.8000],
[-87.5500, 41.9000],
[-87.6500, 41.9000],
[-87.6500, 41.8000]
]]
},
properties: {}
};

// Step 2: Get points
const points = await fetch(
'https://graph.quarticle.ro/graph/api/v1/reports/portfolio/points/selection',
{
method: 'POST',
headers: {
'Authorization': `${apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
source,
shape: area,
filters: [{ field: 'oe_id', value: source }],
properties: ['name', 'value', 'property_type']
})
}
).then(r => r.json());

console.log(`Found ${points.length} properties`);

// Step 3: Accumulate metrics
const analysis = await fetch(
'https://graph.quarticle.ro/graph/api/v1/reports/portfolio/accumulation/selection',
{
method: 'POST',
headers: {
'Authorization': `${apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
source,
shape: area,
filters: [{ field: 'oe_id', value: source }],
aggregationColumns: ['value', 'occupancy_rate']
})
}
).then(r => r.json());

console.log('Portfolio metrics:', analysis[0].analysis);

return {
pointCount: points.length,
metrics: analysis[0].analysis
};
}

const results = await portfolioAnalysis();
console.log(JSON.stringify(results, null, 2));

Use Cases

  • Geographic market analysis - Understand property distribution and value by location
  • Risk assessment - Identify concentrations and exposure in specific areas
  • Performance reporting - Create market-level summaries for stakeholders
  • Due diligence - Analyze acquisition targets and surrounding markets
  • Portfolio optimization - Identify gaps or overlaps in coverage

Next Steps