Build your first Company Tear Sheet with the AlphaSense SDK
This how-to guide will lead developers through building a standard Company Tear Sheet to give the latest sentiment, topics and information about a company.
Quick Start & Starting From Scratch
Before diving into the quick start guide or starting from scratch, ensure you meet the following requirements:
Requirements
- Node.js: Version 14.0.0 or higher. You can check your current version by running
node -v
in your terminal. - Programming Language: Ensure you have the latest version of your preferred programming language installed. For JavaScript/TypeScript projects, the Node.js version requirement applies.
You can create a new project with the help of the project template. To create a new project, run the following command:
npx @alphasense/sdk-create-app my-company
This command will create a new project with the following structure:
my-dashboard
├── node_modules
├── alphasense.config.ts
├── index.ts
├── package.json
└── tsconfig.json
After updating the configuration (alphasense.config.ts file), you can generate the typings for the queries by running the following command:
npm run generate
After generating the typings, you can start using the SDK in your project! Update the index.ts file however you want, and you can run the code with the following command:
npm run dev
You can see the example result in the console if you have a valid configuration.
Configuration
The SDK checks for the configuration for the following inputs to make sure the SDK is propertly authenticated:
// Typescript (alphasense.config.ts)
import {AlphaSenseConfig} from '@alphasense/sdk-client'
const config: AlphaSenseConfig = {
username: '<your-username>',
password: '<your-password>',
apiKey: '<your-api-key>',
clientId: '<your-client-id>',
clientSecret: '<your-client-secret>',
}
export default config
Building the Search Queries
To start, you will need to build the parameters that you want to use for each of the queries around
the specific company. We will create a new file called api.ts
that will contain everything in
relation to the 3 different queries. Here is an example of what parameters you will need to build
the company page:
const params = {
company: {
inputs: [{tickerCode: 'MSFT'}],
},
summaryDocument: {
filter: {
date: {preset: 'LAST_90_DAYS'},
companies: {ids: ['MSFT'], primaryOnly: true},
types: {ids: ['3']},
},
},
document: {
filter: {
keyword: {query: 'positive'},
date: {preset: 'LAST_12_MONTHS'},
companies: {ids: ['MSFT'], primaryOnly: true},
},
},
}
Searching the Documents
After you have your parameters ready, you can start building each of the requests. First we will start with the company topics request:
const pullCompanyTopics = async (inputs: [CompanyIdInput]) => {
const client = await createClient()
return client.query({
companies: {
id: true,
name: true,
trendingTopics: {
topics: {
name: true,
relevanceScore: true,
sentimentCount: {
total: true,
positive: true,
negative: true,
neutral: true,
},
},
},
__args: {
inputs,
},
},
})
}
Next, we can build the request to pull down all the latest company summaries:
const pullCompanySummaries = async (filter: Record<string, any>) => {
const client = await createClient()
return client.query({
search: {
totalCount: true,
documents: {
id: true,
title: true,
releasedAt: true,
aiSummaryModules: {
type: true,
topics: {
id: true,
on_AISummary: {
title: true,
items: {
content: true,
citations: {
document: {
id: true,
},
},
},
},
on_QAndAAISummary: {
title: true,
items: {
question: {
content: true,
citations: {
document: {
id: true,
},
},
},
answer: {
content: true,
citations: {
document: {
id: true,
},
},
},
},
},
},
},
},
__args: {
filter,
},
},
})
}
Lastly, we will build the query to pull the latest documents that are related to the company and tie the queries into a single fumnction that calls each query:
const searchDocuments = async (filter: Record<string, any>) => {
const client = await createClient(config)
const resp = await client.query({
search: {
documents: {
id: true,
title: true,
releasedAt: true,
type: {
ids: true,
},
snippets: {
statements: {
text: true,
hitOffsets: {
start: true,
end: true,
},
},
},
},
__args: {
filter,
},
},
})
return resp?.search?.documents || []
}
async function fetchAllResults() {
const documents = await searchDocuments(params.document.filter)
const summaries = await pullCompanySummaries(params.summaryDocument.filter)
const topics = await pullCompanyTopics(params.company.inputs)
return {documents, summaries, topics}
}
export default fetchAllResults
Each of the result sets will be a different feed for a section of the dashboard.
Building the Company Tear Sheet
In a separate file index.ts
, you can build a Company Tear Sheet by displaying the 3 analysis that
we ran in api.ts
:
To start you will need to import the necessary libraries and instantiate the server and the DOM
import express from 'express'
import {JSDOM} from 'jsdom'
import fetchAllResults from './api'
const app = express()
const port = 3000
After importing the required packages we will need to start generating the Tear Sheet. We will focus on the dom, some of the stiles and the structure of the page before diving into each section:
async function generateTearSheet(): Promise<string> {
// Replace file reading with fetchAllResults query
const { documents, summaries, topics } = await fetchAllResults();
if (!Array.isArray(topics?.companies?.[0]?.trendingTopics?.topics)) {
throw new Error('Topics is not an array');
}
const dom = new JSDOM('<!DOCTYPE html><html><body></body></html>');
const { document } = dom.window;
const style = document.createElement('style');
style.textContent = `
body { font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; }
h1, h2 { color: #333; }
.widget { background: #f0f0f0; padding: 15px; margin-bottom: 20px; border-radius: 5px; }
.topic { display: inline-block; background: #e0e0e0; padding: 5px 10px; margin: 5px; border-radius: 15px; }
`;
document.head.appendChild(style);
const title = document.createElement('h1');
title.textContent = 'Company Tear Sheet';
document.body.appendChild(title);
Continuing to add onto the first function we can focus in on everything needed to create the summary widget that provides the latest information about the company from their most recent earnings call
// Summaries widget
const summariesWidget = document.createElement('div')
summariesWidget.className = 'widget'
summariesWidget.innerHTML = '<h2>Key Information</h2>'
const summaryList = document.createElement('ul')
if (
summaries &&
summaries.search &&
summaries.search.documents &&
summaries.search.documents[0] &&
summaries.search.documents[0].aiSummaryModules
) {
const earningsReview =
summaries.search.documents[0].aiSummaryModules.find(
module => module?.type === 'EarningsReview',
) ?? null
if (earningsReview && earningsReview.topics) {
earningsReview.topics.forEach(topic => {
if (topic) {
const topicHeader = document.createElement('h3')
topicHeader.textContent = topic.title || 'Untitled Topic'
summaryList.appendChild(topicHeader)
const topicItems = document.createElement('ul')
if ('items' in topic && Array.isArray(topic.items)) {
topic.items.forEach(item => {
if ('content' in item && typeof item.content === 'string') {
const li = document.createElement('li')
li.textContent = item.content
topicItems.appendChild(li)
}
})
}
summaryList.appendChild(topicItems)
}
})
}
} else {
console.error('Summaries data is not in the expected format:', summaries)
}
summariesWidget.appendChild(summaryList)
document.body.appendChild(summariesWidget)
Next, we can look at the latest topic information. What topics are the most important to the company and what are the key drivers. AlphaSense automatically pulls this from their transcripts to give the team a good idea of what is on the C-suite's mind.
// Topics widget
const topicsWidget = document.createElement('div')
topicsWidget.className = 'widget'
topicsWidget.innerHTML = '<h2>Relevant Topics</h2>'
;(topics?.companies[0]?.trendingTopics?.topics ?? [])
.sort((a, b) => (b.relevanceScore ?? 0) - (a.relevanceScore ?? 0))
.slice(0, 10)
.forEach(topic => {
const topicSpan = document.createElement('span')
topicSpan.className = 'topic'
topicSpan.textContent = topic.name ?? 'Unknown Topic'
topicsWidget.appendChild(topicSpan)
})
document.body.appendChild(topicsWidget)
Lastly, we will focus on the Documents section that shows the latest documents related to the company. It will let the client know if any new press releases or filings are top of mind for analysis of that company:
// Documents widget
const documentsWidget = document.createElement('div');
documentsWidget.className = 'widget';
documentsWidget.innerHTML = '<h2>Key Documents</h2>';
const docList = document.createElement('ul');
documents.forEach(doc => {
const li = document.createElement('li');
li.innerHTML = `<strong>${doc.title || 'No title available'}</strong>`;
docList.appendChild(li);
});
documentsWidget.appendChild(docList);
document.body.appendChild(documentsWidget);
return dom.serialize();
}
Finishing it up with actually generating the tearsheet and opening the server to view the page
app.get('/', async (req, res) => {
try {
const tearSheet = await generateTearSheet()
res.send(tearSheet)
} catch (error) {
console.error('Error generating tear sheet:', error)
res.status(500).send('Error generating tear sheet')
}
})
app.listen(port, () => {
console.log(`Server running at http://localhost:${port}`)
})
Finally, run the app using the following command:
npm run dev
Then, open your browser and navigate to the following URL to see the result: http://localhost:3000
Thank you for following along! This is a simple example of how to build a custom Company Tear Sheet with the AlphaSense SDK.