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​