# Exposure by Sector

Canonical page: https://www.adaptabletools.com/docs/showcase-demos-exposure-by-sector

**Example: Showcase: Exposure by Sector**

Demo project (Vanilla); the files without a marker are shown below:

```text
src/
  adaptableOptions.ts
  agGridModules.ts     [template]
  columnDefs.ts
  gridOptions.ts
  index.ts             [template]
  onAdaptableReady.ts  [template]
  rowData.ts
  styles.css           [template]
index.html             [template]
package.json           [template]
tsconfig.json          [template]
```

Files marked `[template]` are the same in every demo; see the [demo template](https://www.adaptabletools.com/llms/demo-template.md#vanilla).

**`src/adaptableOptions.ts`**

```ts
import {AdaptableOptions} from '@adaptabletools/adaptable';
import {ExposureRow} from './rowData';

export const adaptableOptions: AdaptableOptions<ExposureRow> = {
  primaryKey: 'id',
  adaptableId: 'Showcase: Exposure by Sector',
  exportOptions: {
    appendFileTimestamp: true,
    exportDateFormat: 'yyyy-MM-dd',
    exportDataFormat: 'formattedValue',
  },
  initialState: {
    Dashboard: {
      Tabs: [
        {
          Name: 'Reporting',
          Toolbars: ['Layout', 'Export', 'GridFilter'],
        },
      ],
      ModuleButtons: ['Layout', 'Export', 'CalculatedColumn'],
    },
    StatusBar: {
      StatusBars: [
        {
          Key: 'Center Panel',
          StatusBarPanels: ['Layout', 'Export'],
        },
      ],
    },
    Theme: {CurrentTheme: 'dark'},
    NamedQuery: {
      NamedQueries: [
        {
          Name: 'Material Exposure',
          Expression:
            '[weightPct] > 0.05 OR ABS([pnlPct]) > 0.03',
        },
      ],
    },
    Layout: {
      CurrentLayout: 'Sector × Region',
      Layouts: [
        {
          Name: 'Positions',
          AutoSizeColumns: true,
          TableColumns: [
            'symbol',
            'sector',
            'region',
            'book',
            'marketValue',
            'pnl',
            'pnlPct',
            'weightPct',
            'varContribution',
            'sector_market_value',
            'rating',
          ],
        },
        {
          Name: 'By Sector (grouped)',
          AutoSizeColumns: true,
          SuppressAggFuncInHeader: true,
          RowGroupedColumns: ['sector'],
          RowGroupValues: {
            RowGroupDefaultBehavior: 'expanded',
          },
          ColumnPinning: {'ag-Grid-AutoColumn': 'left'},
          TableAggregationColumns: [
            {ColumnId: 'marketValue', AggFunc: 'sum'},
            {ColumnId: 'pnl', AggFunc: 'sum'},
            {
              ColumnId: 'pnlPct',
              AggFunc: {
                type: 'weightedAverage',
                weightedColumnId: 'marketValue',
              },
            },
            {ColumnId: 'varContribution', AggFunc: 'sum'},
            {ColumnId: 'id', AggFunc: 'count'},
          ],
          TableColumns: [
            'ag-Grid-AutoColumn',
            'symbol',
            'region',
            'book',
            'marketValue',
            'pnl',
            'pnlPct',
            'weightPct',
            'varContribution',
            'sector_market_value',
            'rating',
          ],
        },
        {
          Name: 'Sector × Region',
          SuppressAggFuncInHeader: true,
          PivotGroupedColumns: ['sector'],
          PivotColumns: ['region'],
          PivotAggregationColumns: [
            {ColumnId: 'marketValue', AggFunc: 'sum', Total: true},
            {ColumnId: 'pnl', AggFunc: 'sum', Total: true},
            {ColumnId: 'varContribution', AggFunc: 'sum', Total: true},
            {ColumnId: 'id', AggFunc: 'count', Total: true},
          ],
        },
        {
          Name: 'By Book',
          SuppressAggFuncInHeader: true,
          PivotGroupedColumns: ['book'],
          PivotColumns: ['region'],
          PivotAggregationColumns: [
            {ColumnId: 'marketValue', AggFunc: 'sum', Total: 'before'},
            {ColumnId: 'pnl', AggFunc: 'sum', Total: true},
            {ColumnId: 'weightPct', AggFunc: 'sum', Total: 'after'},
          ],
        },
        {
          Name: 'Material Names',
          AutoSizeColumns: true,
          TableColumns: [
            'symbol',
            'sector',
            'region',
            'book',
            'marketValue',
            'pnl',
            'pnlPct',
            'weightPct',
            'varContribution',
          ],
          GridFilter: {
            Expression: 'QUERY("Material Exposure")',
          },
        },
      ],
    },
    CalculatedColumn: {
      CalculatedColumns: [
        {
          FriendlyName: 'Sector Market Value',
          ColumnId: 'sector_market_value',
          Expression: 'SUM{[marketValue], GROUP_BY([sector])}',
          CalculatedColumnSettings: {
            DataType: 'number',
            Filterable: true,
            Groupable: true,
          },
        },
      ],
    },
    FormatColumn: {
      FormatColumns: [
        {
          Name: 'format-negative-pnl',
          Scope: {ColumnIds: ['pnl', 'pnlPct']},
          Rule: '[pnl] < 0',
          Style: {ForeColor: '#ff6b6b'},
        },
        {
          Name: 'format-positive-pnl',
          Scope: {ColumnIds: ['pnl', 'pnlPct']},
          Rule: '[pnl] > 0',
          Style: {ForeColor: '#4ade80'},
        },
        {
          Name: 'format-high-var',
          Scope: {ColumnIds: ['varContribution']},
          Rule: '[varContribution] > 0.04',
          Style: {
            BackColor: 'var(--ab-color-palette-3)',
            ForeColor: 'var(--ab-color-palette-4)',
          },
        },
        {
          Name: 'format-market-value',
          Scope: {
            ColumnIds: ['marketValue', 'sector_market_value'],
          },
          DisplayFormat: 'Million',
        },
        {
          Name: 'format-pnl',
          Scope: {ColumnIds: ['pnl']},
          DisplayFormat: 'Accounting',
        },
        {
          Name: 'format-percentages',
          Scope: {ColumnIds: ['pnlPct', 'weightPct', 'varContribution']},
          DisplayFormat: 'Percentage',
        },
      ],
    },
    Export: {
      CurrentReport: 'Committee Pack',
      CurrentFormat: 'Excel',
      Reports: [
        {
          Name: 'Committee Pack',
          ReportColumnScope: 'ScopeColumns',
          ReportRowScope: 'AllRows',
          Scope: {
            ColumnIds: [
              'symbol',
              'sector',
              'region',
              'book',
              'marketValue',
              'pnl',
              'pnlPct',
              'weightPct',
              'varContribution',
              'sector_market_value',
              'rating',
            ],
          },
        },
        {
          Name: 'Material Exposure',
          ReportColumnScope: 'ScopeColumns',
          ReportRowScope: 'ExpressionRows',
          Scope: {
            ColumnIds: [
              'symbol',
              'sector',
              'region',
              'book',
              'marketValue',
              'pnl',
              'pnlPct',
              'weightPct',
              'varContribution',
            ],
          },
          Expression: 'QUERY("Material Exposure")',
        },
      ],
    },
  },
};
```

**`src/rowData.ts`**

```ts
export type ExposureRegion = 'Americas' | 'EMEA' | 'APAC';
export type ExposureBook = 'Equities' | 'Fixed Income' | 'Multi-Asset';
export type ExposureRating = 'AAA' | 'AA' | 'A' | 'BBB' | 'BB';

export interface ExposureRow {
  id: number;
  symbol: string;
  sector: string;
  region: ExposureRegion;
  book: ExposureBook;
  marketValue: number;
  pnl: number;
  pnlPct: number;
  weightPct: number;
  varContribution: number;
  rating: ExposureRating;
}

const SECTORS = [
  'Technology',
  'Financials',
  'Healthcare',
  'Energy',
  'Consumer',
  'Industrials',
] as const;

const SYMBOLS = [
  'AAPL',
  'MSFT',
  'NVDA',
  'JPM',
  'GS',
  'UNH',
  'XOM',
  'BP',
  'SAP',
  'NESN',
  'BABA',
  'TSM',
  'CAT',
  'BA',
] as const;

const REGIONS: ExposureRegion[] = ['Americas', 'EMEA', 'APAC'];
const BOOKS: ExposureBook[] = ['Equities', 'Fixed Income', 'Multi-Asset'];
const RATINGS: ExposureRating[] = ['AAA', 'AA', 'A', 'BBB', 'BB'];

function pseudoRandom(seed: number): number {
  const x = Math.sin(seed * 3131) * 10000;
  return x - Math.floor(x);
}

const generated: ExposureRow[] = [];

for (let i = 1; i <= 96; i++) {
  const marketValue = Math.round(2_000_000 + pseudoRandom(i * 11) * 48_000_000);
  const bookWeight = marketValue / 520_000_000;
  // Stored as decimal ratios (e.g. 0.0543 = 5.43%) — formatted with the Percentage preset.
  const pnlPct =
    Math.round((pseudoRandom(i * 7) - 0.45) * 800) / 10000;
  const pnl = Math.round(marketValue * pnlPct);

  generated.push({
    id: i,
    symbol: SYMBOLS[Math.floor(pseudoRandom(i * 5) * SYMBOLS.length)],
    sector: SECTORS[Math.floor(pseudoRandom(i * 3) * SECTORS.length)],
    region: REGIONS[Math.floor(pseudoRandom(i * 13) * REGIONS.length)],
    book: BOOKS[Math.floor(pseudoRandom(i * 17) * BOOKS.length)],
    marketValue,
    pnl,
    pnlPct,
    weightPct: Math.round(bookWeight * 10000) / 10000,
    varContribution: Math.round(bookWeight * 42 * 100) / 10000,
    rating: RATINGS[Math.floor(pseudoRandom(i * 19) * RATINGS.length)],
  });
}

export const rowData: ExposureRow[] = generated;
```

**`src/columnDefs.ts`**

```ts
import {ColDef} from 'ag-grid-enterprise';

export const columnDefs: ColDef[] = [
  {field: 'symbol', cellDataType: 'text', width: 90},
  {field: 'sector', cellDataType: 'text', enableRowGroup: true, enablePivot: true},
  {
    field: 'region',
    cellDataType: 'text',
    enableRowGroup: true,
    enablePivot: true,
  },
  {
    field: 'book',
    cellDataType: 'text',
    enableRowGroup: true,
    enablePivot: true,
  },
  {
    field: 'marketValue',
    headerName: 'Market Value',
    cellDataType: 'number',
    type: 'rightAligned',
    enableValue: true,
  },
  {
    field: 'pnl',
    headerName: 'P&L',
    cellDataType: 'number',
    type: 'rightAligned',
    enableValue: true,
  },
  {
    field: 'pnlPct',
    headerName: 'P&L %',
    cellDataType: 'number',
    type: 'rightAligned',
    enableValue: true,
    aggFunc: 'avg',
  },
  {
    field: 'weightPct',
    headerName: 'Weight %',
    cellDataType: 'number',
    type: 'rightAligned',
    enableValue: true,
    aggFunc: 'sum',
  },
  {
    field: 'varContribution',
    headerName: 'VAR Contrib',
    cellDataType: 'number',
    type: 'rightAligned',
    enableValue: true,
    aggFunc: 'sum',
  },
  {field: 'rating', cellDataType: 'text', enableRowGroup: true, enablePivot: true},
  {field: 'id', hide: true, editable: false, enableValue: true},
];
```

**`src/gridOptions.ts`**

```ts
import {GridOptions, themeBalham} from 'ag-grid-enterprise';

import {columnDefs} from './columnDefs';
import {ExposureRow, rowData} from './rowData';

export const gridOptions: GridOptions<ExposureRow> = {
  theme: themeBalham,
  defaultColDef: {
    resizable: true,
    sortable: true,
    editable: false,
    filter: true,
    floatingFilter: true,
  },
  columnDefs: columnDefs,
  rowData: rowData,
  sideBar: true,
  suppressMenuHide: true,
  columnMenu: 'new',
  cellSelection: true,
  statusBar: {
    statusPanels: [
      {statusPanel: 'agTotalRowCountComponent', align: 'left'},
      {statusPanel: 'agFilteredRowCountComponent'},
      {
        key: 'Center Panel',
        statusPanel: 'AdaptableStatusPanel',
        align: 'center',
      },
    ],
  },
};
```
