Metropolis DevZone > Data Integrator's Guide > Prism Overview > Prism Examples

Prism lets you quickly import external databases into Palantir by creating data providers. Each section of this page includes a Carbon and a PostgreSQL script that creates a working data provider.

Prerequisites
Before you begin, you should read the Prism Overview and be familiar with the Carbon Reference. You should also be able to run arbitrary scripts on a PostgreSQL database.
No. Name Topics
1 Connecting to Databases
  • Database connection
2 Models, Metrics, and Properties
  • Model sources
  • Metrics
  • Properties
  • TimeSeries data
3 Updating Data Using Events and Triggers
  • Units
  • Variables
  • Events
  • Triggers
  • Filters
4 Parameters and Documentation
  • Metrics with parameters
  • Metric documentation
5 Column Transforms and Closures
  • Imported Java types
  • Closures
  • Output type
6 Advanced Properties
  • Multi-valued properties
  • Time-sensitive properties
  • Null values in database
7 Historical Membership
  • Multi-valued time-sensitive properties
  • Model types as property outputs
8 Resolving Models
  • Resolution properties
9 Object Time Series - Strings
  • Import object time series data
10 Object Time Series - Models
  • Import object time series data

Connecting to Databases

The scripts in this example add the stocks MYFIRSTSTOCK and MYSECONDSTOCK to Palantir, as well as metrics that return each stock's name, symbol, trading country, and closing price time series. The Carbon script included in this example logs into a database and exposes it as a data provider in Palantir. In order to connect to a database, the Carbon file must have a model type block as well as the Config block.

  1. Run this PostgreSQL script on your database. It will add the tables you need and fill them with example data.
    Performance Tip
    Palantir builds a set of models from the model source's id columns using a SQL 'SELECT DISTINCT' clause. For that reason, your id columns should be as unique as possible (ideally, using a SQL 'UNIQUE' constraint) to maximize performance.
  2. Create a new file in /<your_palantir_server>/providers/prism and name it what you would like your data provider to be called in Palantir (i.e., myExampleProvider). Add the following Carbon script to it, then change the login information in the Config block to match your database's login information.
    Learning Tip
    Read the comments in the provided Carbon script to understand how the script works.
    import com.palantir.finance.commons.data.model.*
    
    Config {
        Database {
            driver = "org.postgresql.Driver"
            url = "jdbc:postgresql://myServerName:myPortNumber/myDatabaseName"
            username = "myUsername"
            password = "myPassword"
        }
    }
    
    CommonStock {
        "models" {
            modelSource = true 
            
            // Creates the model-id. Taken together, The values in 'columns' 
            // uniquely identify each model.
            id = [columns: ["id"], tokens: ["symbol"]]
            
            // For instance, calling myCommonStock.country() returns the value
            // in the countrytradingin column.
            properties << [id: "name", countrytradingin: "country"]
        }
    
        "timeseries" { 
            // There should be a foreign key constraint on timeseries.id that 
            // references models.id. If there isn't, and timeseries.id contains a value
            // that isn't in in models.id (case-sensitive), you won't be able to access
            // your timeseries data.
            id = [columns: ["id"]]
            Timestamp {
                // For instance, calling myGenericInstrument.close() 
                // returns a TimeSeries made from the 'date' and 'metric1' columns
                dateColumn = Column(name: "date", dateFormat: FULLDATE)
                metrics << [ metric1: "close"]
            }
        }
    }
    
  3. (Re)start your Palantir instance's Dispatch Server and Client. Open Explorer, change the starting universe to all models and add a Provider filter. Your data provider (whose name is the same as the name of your Carbon script file) will appear in the list of providers. Now you're ready to start importing models, metrics, and properties from your database.

Models, Metrics, and Properties

This example is a continuation of the previous example. We use the metrics created and apply them to the Prism provider.

  1. Open Calculator and enter MYFIRSTSTOCK.close() (whose final value is 90), MYFIRSTSTOCK.name() ("myFirstStock"), and MYFIRSTSTOCK.country() ("United States"). Now you've successfully imported your first models, metrics, and properties.

Metric Pitfall Example

The scripts in this example import Instruments that represent weather observations in New York City and Los Angeles. The database defines two types of temperatures (daily high and daily low), so we also import a metric whose parameter lets you decide which temperature type to return. This is structured similarly to the metric in the bank account example in that the metric’s parameter acts as the Carbon filter’s condition, but is chosen in the Client.

  1. Run this PostgreSQL script on your database. It will add the tables you need and fill them with example data. Below is a sample of data from the database.

    Table 1: LA Temperatures

    date Temp_Type Temperature_Fahrenheit
    2010-03-10 High 60
    2010-03-10 Low 48
    2010-03-11 High 64
    2010-03-11 Low 49

    Table 2: NY Temperatures

    date Temp_Type Temperature_Fahrenheit
    2010-03-10 High 41
    2010-03-10 Low 36
    2010-03-11 High 53
    2010-03-11 Low 43


  2. Create a new file in /<your_palantir_server>/providers/prism and name it Weather.carbon. Add the following Carbon script to it, and then change the login information in the Config block to match your database’s login information.
    import com.palantir.finance.commons.data.model.*
    
    Config {
        Database {
            driver = "org.postgresql.Driver"
            url = "jdbc:postgresql://myServerName:myPortNumber/myDatabaseName"
            username = "myUsername"
            password = "myPassword"
        }
    }
    
    GenericInstrument {
    	'la_temperatures' {
    		def indicator = Parameter(name: "temperatureParameter", column: "temp_type", optionsFromColumn: true, description: "Daily temperature type (high/low)")
    		// The parameter that indicates which type of temperatures we want. 
    		def tempMetric = Metric(token: "dailyTemperature", parameters: [indicator])
    		// The Metric that returns the temperature for the specified date of the specified type; the token is the name we use in the Client. 
    		modelSource = true
    		// We set the model source to true since this table contains an initial universe of models for our instrument (weather) model.
    		id = [columns: ["date"], tokens: ["symbol", "name"]]
    		Timestamp {
    			dateColumn = Column(name: "date", dateFormat: FULLDATE)
    			// Since we have dates in our data, we need a timestamp block, which requires dateColumn to indicate the column where 
    			// these dates are located, as well as their format. 
    			metrics << [temperature_fahrenheit: tempMetric]
    			// This metric will apply our previously defined metric to the temperature_fahrenheit column.
    		}
    	}
    	'ny_temperatures' {
    		def indicator = Parameter(name: "temperatureParameter", column: "temp_type", optionsFromColumn: true, description: "Daily temperature type (high/low)")
    		def tempMetric = Metric(token: "dailyTemperature", parameters: [indicator])
    		modelSource = true
    		id = [columns: ["date"], tokens: ["symbol", "name"]]
    		Timestamp {
    			dateColumn = Column(name: "date", dateFormat: FULLDATE)
    			metrics << [temperature_fahrenheit: tempMetric]
    		}
            }
    }
    
  3. (Re)start your Palantir instance’s Dispatch Server and Client. Open Calculator and enter _2010_03_07.dailyTemperature(“high”) Notice the autocomplete window displays the choice of ‘high’ or ’low’ as the parameter for dailyTemperature, which refers to a unique value in the temperature_Fahrenheit column from our tables.
  4. Continue to explore this metric on March 10th and 11th to see the following results.

    Notice that all the low temperatures are of Los Angeles, and all the high temperatures are of New York City; there's no way to dictate which city's temperature to return. Since both tables have identical formatting and metrics, the behavior is undefined in how it determines which tables to query. To fix this, we rename the metrics.
  5. Go back into your Carbon file. Replace the Carbon script with the new script below. Remember to input your login credentials in the Config block.
    import com.palantir.finance.commons.data.model.*
    
    Config {
        Database {
            driver = "org.postgresql.Driver"
            url = "jdbc:postgresql://myServerName:myPortNumber/myDatabaseName"
            username = "myUsername"
            password = "myPassword"
        }
    }
    
    GenericInstrument {
    	'la_temperatures' {
    		def indicator = Parameter(name: "temperatureParameter", column: "temp_type", optionsFromColumn: true, description: "Daily temperature type (high/low)")
    		def tempMetric = Metric(token: "dailyLATemperature", parameters: [indicator])
    		modelSource = true
    		id = [columns: ["date"], tokens: ["symbol", "name"]]
    		Timestamp {
    			dateColumn = Column(name: "date", dateFormat: FULLDATE)
    			metrics << [temperature_fahrenheit: tempMetric]
    		}
    	}
    	'nyc_weather' {
    		def indicator = Parameter(name: "temperatureParameter", column: "temp_type", optionsFromColumn: true, description: "Daily temperature type (high/low)")
    		def tempMetric2 = Metric(token: "dailyNYTemperature", parameters: [indicator])
    		modelSource = true
    		id = [columns: ["date"], tokens: ["symbol", "name"]]
    		Timestamp {
    			dateColumn = Column(name: "date", dateFormat: FULLDATE)
    			metrics << [temperature_fahrenheit: tempMetric2]
    			}
            }
    }
    
  6. Restart your Palantir instance’s Dispatch Server and Client. Open Calculator and enter _2010_03_10.DailyNYTemperature(“high”), _2010_03_10.DailyNYTemperature(“low”) , _2010_03_10.DailyLATemperature(“high”) , and _2010_03_10.DailyLATemperature(“low”). The returned values are:

Updating Data Using Events and Triggers

The scripts in this example import the stocks MYFIRSTSTOCK and MYSECONDSTOCK, as well as data for MYFIRSTSTOCK's closing price. It also adds events and triggers so that Palantir automatically reloads data from the data provider at regular intervals. Additionally, since we want to work with a subset of the rows in the database we'll use a filter to select only the rows where that condition is true (similar to a SQL 'WHERE' clause).

  1. Run this PostgreSQL script on your database. It will add the tables you need and fill them with example data. The table below is a sample of the data in the "timeseries" table.
    id date tsvalue1 units
    myFirstStock 2012-07-19 100 USD/share
    myFirstStock 2012-07-19 200 GBP/share
    myFirstStock 2012-07-18 100 USD/share
    myFirstStock 2012-07-18 200 GBP/share


  2. Create a new file in /<your_palantir_server>/providers/prism and name it what you would like your data provider to be called in Palantir (for example, CustomStocks.carbon). Add the following Carbon script to it, then change the login information in the Config block to match your database's login information.
    import com.palantir.finance.commons.data.model.*
    
    Config {
        Database {
            driver = "org.postgresql.Driver"
            url = "jdbc:postgresql://myServerName:myPortNumber/myDatabaseName"
            username = "myUsername"
            password = "myPassword"
        }
    }
    
    
    // Each event updates the data for the given entity in the given scope. Here,
    // the first event will update the data for each PROPERTY specified in ALL Table
    // blocks in this file.
    def propertyEvent = [ Event(entity: PROPERTY, scope: ALL) ]
    def metricEvent = [ Event(entity: METRIC, scope: ALL) ]
    def modelEvent = [ Event(entity: MODEL, scope: ALL)]
    
    
    // The first trigger executes the propertyEvent, the second trigger executes
    // the metricEvent, and the third trigger executes the modelTrigger. They are all 
    // executed every minute on the minute (for instance, 8:00:00, 8:01:00).
    triggers = [
        Trigger(name: "propertyTrigger", 
                cronTime: "0 * * * * ?", 
                events: propertyEvent), 
        Trigger(name: "metricTrigger", 
                cronTime: "0 * * * * ?", 
                events: metricEvent),
        Trigger(name: "modelTrigger",
                cronTime: "0 * * * * ?",
                events: modelEvent) 
    ]
    
    GenericInstrument() {
        
        "models" {
            modelSource = true
            id = [columns: ["id"], tokens: ["symbol", "name"]]
            properties << [countrytradingin: "country"]
        }
    
        "timeseries" {
            id = [columns: ["id"]]
    
            // This filter tag selects only rows from the timeseries table
            // for which timeseries.units = 'USD/share'. Only those rows will
            // become part of the metrics defined in the Timestamp block.
            filter = "timeseries.units = 'USD/share'"
            Timestamp {
                dateColumn = Column(name: "date", dateFormat: FULLDATE)
    
                // This creates a new unit by parsing the values in the 
                // timeseries.units column. Remember that the filter above
                // selects only the rows where timeseries.units = 'USD/share'.
                def dollarsPerShare = ColumnUnit('units')
                metrics << [tsvalue1: Metric(token: "close", unit: dollarsPerShare)]
            }
        }
    }
    
  3. (Re)start your Palantir instance's Dispatch Server and Client. Open Calculator and enter MYFIRSTSTOCK.close() to get a time series created from importing the data in the database. Note that the units of the time series are "USD/share", exactly as the Carbon script defined it by using a ColumnUnit.

    Also, while the server is running, update the values in "models.countrytradingin". The events and triggers reload this data from the provider automatically every minute, so within a minute of updating the database the country() metric will return these new values.

Parameters and Documentation

The scripts in this example import Instruments that represent bank accounts and time series that represent those accounts' balances over time. The database defines the time series in two distinct units, so our scripts import a metric whose parameter lets you choose whether to return the time series in one unit or the other. The parameter performs the same function as a Carbon filter, except that the filter's condition is the metric's parameter (that you choose in the Client).

  1. Run this PostgreSQL script on your database. It will add the tables you need and fill them with example data. Below is a sample of data from the database.
    id date tsvalue1 units
    12345 2012-07-17 100 USD
    12345 2012-07-17 200 GBP
    12345 2012-07-16 100 USD
    12345 2012-07-16 200 GBP


  2. Create a new file in /<your_palantir_server>/providers/prism and name it what you would like your data provider to be called in Palantir. Add the following Carbon script to it, then change the login information in the Config block to match your database's login information.
    import com.palantir.finance.commons.data.model.*
    import com.palantir.finance.commons.data.model.Country
    import com.palantir.finance.commons.service.ontology.model.*
    
    Config {
        Database {
    	driver = "org.postgresql.Driver"
    	url = "jdbc:postgresql://myServerName:myPortNumber/myDatabaseName"
    	username = "myUsername"
    	password = "myPassword"
        }
    }
    
    // The Metric Documentation
    def desc = Documentation(
        name: "Balance of Bank Account", 
        examples: ["_12345.balance(\"USD\")"], 
        tags: ["bank"], 
        description: "Returns a time series that represents the balance of the specified bank account.")
    
    // The Parameter
    def myParameter = Parameter(
        name: "unitsParameter", 
        column: "units", 
        optionsFromColumn: true, 
        description: "The currency.")
    
    // The Metric
    def myMetric = Metric(
        token: "balance", 
        parameters: [myParameter], 
        documentation: desc)
    
    GenericInstrument() {
        acct_open {
     	modelSource = true
    	id = [ columns: ["account_number"], tokens: ["name", "symbol"] ]
    	properties << [acct_country: Property(token: "country", output: Country.class)]
        }
    
        acct_balance {
    	id = [ columns: ["account_number"]]
            Timestamp {
                dateColumn = Column(name: "date", dateFormat: FULLDATE)
    	    metrics << [balance: myMetric]
    	}
        }  
    }
    
    Country() {
        country_table {
    	modelSource = true
            id = [ columns: ["country"], tokens: ["country", "name", "symbol"]]
        }
    }
    
    
  3. (Re)start your Palantir instance's Dispatch Server and Client. Open Calculator and enter _12345.balance("USD") (model tokens cannot begin with numbers or special characters, so Palantir automatically prefixes these tokens with the '_' character). Notice that the autocomplete window displays a list of choices for the string parameter. Each of these choices is a distinct value in the units column that Prism automatically identified when it loaded the data provider.

    Refer back to the database. We used the parameter "USD", so the metric returned a time series made from the rows where the value in the units column was "USD". You can verify that the other rows are excluded by noting that the time series in Calculator is a constant value of 100.

Also, verify that the metric documentation looks like this:

Column Transforms and Closures

The scripts in this example import models that represent treasury yields over given periods and properties that define each treasury yield's name, description, country, and tenor. The tenor is stored in the database as a string, so the Carbon script defines a column transform (or closure) to transform the string value in the database to the Java type org.joda.time.Period (that represents a period of time). The period property then returns that Period object rather than the string.

  1. Run this PostgreSQL script on your database. It will add the tables you need and fill them with example data.
  2. Create a new file in /<your_palantir_server>/providers/prism and name it what you would like your data provider to be called in Palantir. Add the following Carbon script to it, then change the login information in the Config block to match your database's login information.
    import com.palantir.finance.commons.data.model.*
    // Because Carbon is an addition to Groovy, and Groovy is tightly coupled with Java
    // libraries, you can add Java classes and packages. The Period class is such a class.
    import org.joda.time.Period
    
    Config {
        Database {
            driver = "org.postgresql.Driver"
    	url = "jdbc:postgresql://myServerName:myPortNumber/myDatabaseName"
    	username = "myUsername"
    	password = "myPassword"
        }
    }
    
    // The closure is similar to an anonymous function. In the following closure, note
    // that the method calls and syntax are from Java libraries. Methods such as 
    // parseInt(), substring(), and the Period constructor used are all specified in 
    // Java libraries.
    def TenorClosure = { it -> // 'it' is the input
        final Period p;
        int number = Integer.parseInt(it.substring(1, it.length() - 1));
        if (it.toLowerCase().endsWith("y")) {
            p = new Period(number, 0, 0, 0, 0, 0, 0, 0);
        } else {
            p = new Period(0, number, 0, 0, 0, 0, 0, 0);
        }
        return p; // every closure should return a value 
    }
    
    GenericInstrument() {
        'example_db' {
            modelSource = true
    	id = [ columns: ['model'], tokens: ['symbol'] ]
    	properties << 'name' << 'description' << 'country'
    	// The variable we defined is a 'transform' applied to the column. Every value in that column will be fed through
    	// the transform function as an input, and the function's output (not the column's values) will make up the 'tenor' 
    	// property's output. Also note that the Property function defines the output type as Period.class (remember that
    	// our transform returns a Period object.)
    	properties << [(Column(name: 'tenor', transform: TenorClosure)): Property(token: 'tenor', output: Period.class)]
        }
    }
    
  3. (Re)start your Palantir instance's Dispatch Server and Client. Open Calculator and enter BC_10YEAR.tenor() to see the value returned by our column transform. Enter BC_10YEAR.tenor().getType() to see that Palantir is returning Period objects rather than strings.

Advanced Properties

The scripts in this example import one model, MYCOMPANY, as well as the properties 'name' and 'symbol'. They also add 'departments', a multi-valued property that returns a set rather than a single value, and 'ceo', a time-sensitive property that returns different single values depending on the value-on date.

  1. Run this PostgreSQL script on your database. It will add the tables you need and fill them with example data.
  2. Create a new file in /<your_palantir_server>/providers/prism and name it what you would like your data provider to be called in Palantir. Add the following Carbon script to it, then change the login information in the Config block to match your database's login information.
    import com.palantir.finance.commons.data.model.*
    
    Config {
        Database {
            driver = "org.postgresql.Driver"
    	url = "jdbc:postgresql://myServerName:myPortNumber/myDatabaseName"
    	username = "myUsername"
    	password = "myPassword"
        }
    }
    
    GenericInstrument {
        'companies' {
            modelSource = true
    	id = [columns: ['company'], tokens: ['name', 'symbol']]
    	// A multivalued property returns a set of values rather than a single value. Every value
    	// in the target column ('departments') will be in the set returned by the property. Null
    	// values in the database will not be added to the set. 
    	properties << [departments: Property(token: 'departments', multiValued: true)]
    	Timestamp {
    	    dateColumn = Column(name: 'start_date', dateFormat: FULLDATE)
                // A timeSensitive property still returns only a single value, but that value changes
    	    // as you change the valueOn date. The system creates date intervals for every pair of consecutive 
                // non-null dates, including one last unbounded interval from the last non-null date.
    	    properties << [ceo: Property(token: 'ceo', timeSensitive: true, output: String.class)]
    	}
        }
    }
    
  3. (Re)start your Palantir instance's Dispatch Server and Client. Open Calculator and enter MYCOMPANY.departments(), which returns a set of three strings. Although the database has four rows, multi-valued properties only include the values in the column that are non-null and ignore the rest. This property includes only three strings because the fourth row of the database is empty.

    Also, enter MYCOMPANY.ceo(). If your value-on is set to the current date, this returns "John Doe 4". Although there is no CEO listed for the current date, Palantir's default on-or-before behavior means that the property returns the most recent value if no current value exists. Set the value-on date to any day in 2010 and enter MYCOMPANY.ceo() again. This time, it returns "John Doe 3," because John Doe 3 was the CEO in 2010. Because the property is time-sensitive, it changes as the value-on date changes.

Historical Membership

The scripts in this example import a StockMarketIndex model with a defined history of membership and a (multi-valued and time-sensitive) metric, 'members', which returns a set of the index's members. Because it is a time-sensitive property, members() returns a different set depending on the value-on date.

  1. Run this PostgreSQL script on your database. It will add the tables you need and fill them with example data. Below is a sample of the database. Note that INSTRUMENT_1 is a member of MYINDEX for two separate periods, so it occupies two rows.
    index_instrument_code instrument_code start_date end_date
    MYINDEX INSTRUMENT_1 2009-01-01 2009-10-01
    MYINDEX INSTRUMENT_2 2009-01-01 2011-07-01
    MYINDEX INSTRUMENT_3 2010-01-01 2011-07-01
    MYINDEX INSTRUMENT_1 2010-01-01 2011-07-01
  1. Create a new file in /<your_palantir_server>/providers/prism and name it what you would like your data provider to be called in Palantir. Add the following Carbon script to it, then change the login information in the Config block to match your database's login information.
    import com.palantir.finance.commons.data.model.*
    
    Config {
        Database {
            driver = "org.postgresql.Driver"
            url = "jdbc:postgresql://myServerName:myPortNumber/myDatabaseName"
            username = "myUsername"
            password = "myPassword"
        }
    }
    
    // This block defines models that will make up our membership. A property can only output
    // models that resolve to models provided by the same data provider, so without this block
    // our historical membership would return null rather than a set of values.
    GenericInstrument() {
        'members' {
            modelSource = true
    	id = [columns: ['member_code'], tokens: ['name', 'symbol']]
    	properties << 'description' << 'cusip' << 'countrytradingin'
        }
    }
    
    StockMarketIndex() {
        'index_members' {
            modelSource = true
    	id = [columns: ['index_code'], tokens: ['name', 'symbol']]
    	properties << [member_code: Property(token: 'allMembers', multiValued: true, output: GenericInstrument.class)]
    	Timestamp {
    	    dateColumns = [start: Column(name: 'start_date', dateFormat: FLEXDATE), end: Column(name: 'end_date', dateFormat: FLEXDATE)]
                // Note that this property is both time-sensitive and multi-valued. That means it returns a set of items whose membership
    	    // changes with the value-on date. Also note that the output type is GenericInstrument.class, which is the same type as our
    	    // modelSource block from 'members' defined. 
    	    properties << [member_code: Property(token: 'members', timeSensitive: true, multiValued: true, output: GenericInstrument.class)]
    	}
        }
    }
    
  2. (Re)start your Palantir instance's Dispatch Server and Client. Open Calculator and enter MYINDEX.members(). If your value-on date is the current date, then this will return null because there are no members after early July 2012. Change the value-on date to 2012-01-01, then enter the same metric. Now the metric returns a collection of three instruments, because at that point in time there were three members. Change the value-on date again, this time to 2011-01-01, and enter the metric again. This time there are eight members.



    Open this collection of eight instruments in Table, then add the cusip() metric to the table as a column. Notice that the value returned is the same value as in the "members" table. Even though the members of the index were specified in the "index_members" table, they resolved to models imported from the "members" table. For more information about model resolution, see Resolving Models (below) and Model Overview.



    Open Calculator again and enter MYINDEX.allMembers(), which returns a set of the discrete members of the column "index_members.member_code". In this case, that means it returns a set of every Instrument that has ever been a member of MYINDEX.

Resolving Models

The scripts in this example create two data providers and import several Country and Currency models. The Currencies are resolved to models in the system using the built-in resolution properties, and Countries are resolved between the two data providers using a custom resolution property. The scripts also create two tables that provide data about the same models and then show how to import the data in each table as a single model rather than several (one from each table).

For more information about model resolution and resolution properties, see Model Overview.

  1. Run this PostgreSQL script on your database. It will add the tables you need and fill them with example data. Here is a sample of the database.


    Provider One: "countries_one"

    name code number
    inter_provider_country QN 2
    intra_provider_country QM 1

    Provider One: "countries_two"

    name pop continent area
    intra_provider_country 1024 North America 256

    Provider Two: "countries_three"

    name number
    inter_provider_country 2
  2. Create a new file in /<your_palantir_server>/providers/prism and name it what you would like your data provider to be called in Palantir. Add the following Carbon script to it, then change the login information in the Config block to match your database's login information.
    import com.palantir.finance.commons.data.model.*
    
    Config {
        Database {
            driver = "org.postgresql.Driver"
    	url = "jdbc:postgresql://myServerName:myPortNumber/myDatabaseName"
    	username = "myUsername"
    	password = "myPassword"
        }
    }
    
    Country() {
        // This adds the 'myResolutionNumber' property to the first tier of resolution 
        // properties for the Country model type.
        resolutionProperties = [high: [['number']]]
    
        'countries_three' {
            modelSource = true
    	id = [ columns: ['name'], tokens: ['name', 'symbol'] ]
    	properties << 'number'
        }
    }
    
  3. Create a new file in /<your_palantir_server>/providers/prism and name it what you would like your second data provider to be called in Palantir. Add the following Carbon script to it, then change the login information in the Config block to match your database's login information.
    import com.palantir.finance.commons.data.model.*
    
    Config {
        Database {
            driver = "org.postgresql.Driver"
    	url = "jdbc:postgresql://myServerName:myPortNumber/myDatabaseName"
    	username = "myUsername"
    	password = "myPassword"
        }
    }
    
    Country() {
        'countries_one' {
            modelSource = true
            id = [ columns: ['name'], tokens: ['name', 'symbol'] ]
    	properties << [code: 'countryCode'] << 'number'
        }
        'countries_two' {
    	id = [columns: ['name']]
    	properties << 'pop' << 'continent' << 'area'
        }
    }
    
    Currency() {
        'my_currencies' {
            modelSource = true
    	id = [columns: ['currency_code'], tokens: ['name', 'symbol']]
            // The currencyCode property is the resolution property for the Currency 
    	// model type, so we have to specify it in order to resolve our USD to the 
    	// system's USD.
    	properties << [my_prop: 'myProperty'] << [currency_code: 'currencyCode']
        }
    }
    
  4. (Re)start your Palantir instance's Dispatch Server and Client. Open Explorer, set the starting universe to All models, add a Provider filter, and then select your data providers. Add a getType() column and sort by that. The ExplorerGroup panel at the bottom will show two Country models.

    Note that inter_provider_country is provided by both of your data providers. The inter_provider_country models provided by the two data providers resolved to one because each model had the same value for our custom resolution property, number().

    Also note that intra_provider_country is only displayed once, even though it appeared in two tables in the provider. Prism recognized that the two tables each provided a model with the same model ID (here, the value in the "name" column), so it imported those two models into Palantir as a single one. (For another example of this process, see Historical Membership.)

    If two models from the same provider have the same resolution properties, then neither will be exposed in Palantir (this is called blacklisting). For example, take two models that would resolve if they were imported from two different providers. If they were imported from the same provider instead, they would be blacklisted.

    Open Calculator and enter USD.dataProviders(), then open the result in Table. Because our USD model resolved to the one in Palantir, the list of data providers will include your data provider. Then return to Calculator and enter USD.myProperty to return the custom data the scripts imported from the database.

Object Time Series - Strings

The scripts in this example creates a model and a metric that returns an object time series. The object time series contains series of strings. An object time series is a time series whose values are objects (such as strings) rather than numbers.

  1. Run this PostgreSQL script on your database. It will add the tables you need and fill them with example data.
  2. Create a new file in /<your_palantir_sever>/providers/prism. The file's name will be the name of the data provider in Palantir.
  3. Open the file and paste the following Carbon code (remember to change the login information in the Config block to match your database's login information).
    import com.palantir.finance.commons.data.model.*
    
    Config {
        Database {
            driver = "org.postgresql.Driver"
    	url = "jdbc:postgresql://myServerName:myPortNumber/myDatabaseName"
    	username = "myUsername"
    	password = "myPassword"
        }
    }
    
    GenericInstrument() {
        'hiring_events' {
            modelSource = true
    	id = [columns: ['company'], tokens: ['name', 'symbol']]
    	Timestamp {
    	    dateColumn = Column(name: 'start_date', dateFormat: FLEXDATE)
    	    metrics << [event: Metric(token: 'newHires', output:String.class)]
    	}
        }
    }
    
  1. (Re)start your Palantir instance's Dispatch Server and Client. When you're done, open Calculator and enter MYCOMPANY.newHires(). Open the result in Table. You'll see a list of several recent hires as well as their start dates.

Object Time Series - Models

This script creates two instruments STOCK1 and STOCK2. Each instrument has two metrics countrySeries() and stockSeries() that return object time series. The countrySeries() metric returns models of type Country and the stockSeries() metric returns models of type Stock.

  1. Run this PostgreSQL script on your database to add three tables. The models that we return in the object time series must also be provided by the same provider. That's why our database includes tables for Country and Stock models.
  2. Create a new file in /<your_palantir_sever>/providers/prism. The file's name will be the name of the data provider in Palantir.
  3. Open the file and paste the following Carbon code (remember to change the login information in the Config block to match your database's login information).
    import com.palantir.finance.commons.data.model.*
    Config {
        Database {
            driver = 'org.postgresql.Driver'
    	url = "jdbc:postgresql://myServerName:myPortNumber/myDatabaseName"
    	username = "myUsername"
    	password = "myPassword"
        }
    }
    Country {
        'countries' {
            modelSource = true
            id = [columns: ['country'], tokens: ['countryCode']]
            properties << [country: 'countryCode'] << [country: 'name']
        }
    }
    CommonStock {
        'stocks' {
            modelSource = true
            id = [columns: ['id', 'name']]
            properties << [name: 'symbol'] << 'name'
            properties << [country:  Property(token: 'countryTradingIn', output: Country.class)]
        }
    }
    GenericInstrument {
        'instruments' {
            modelSource = true
            id = [columns: ['symbol'], tokens: ['symbol','name']]
            Timestamp {
                dateColumn = Column(name: 'ts', dateFormat: FULLDATE, frequency: DAYS)
                metrics << [country: Metric(token: 'countrySeries', output: Country.class)]
            }
        }
    }
    

Here's what is going on:

  • The Country and CommonStock blocks create the models that will be returned in the object time series. We provide some properties for those models so that they will resolve to models from other data provider (if they exist). For example, most instances of Palantir include models that represent countries. The system will resolve two country models if they have the same countryCode property.
  • The GenericInstrument block creates the one metric:
    • The countrySeries() metric looks up the entries in the countries table based on 'country' column. In our table, some of the entries in 'instruments.country' are not valid because the countries 'QZ' and '' do not exist in 'countries.country'. These values are omitted from the object time series.

When you're done, (re)start your Palantir instance's Dispatch Server and Client. open Calculator and enter INSTRUMENT1.countrySeries(). Open the result in Table. You'll see a column for the Instrument1's timestamp column (ts) and another column for the corresponding country.

See Also

Prism Overview
Carbon Reference

Need Help? Email us at           © 2014 Palantir Technologies  ·  Terms of Use  ·  Privacy and Security Statement