DSLs and DSVs (Domain Specific Languages and Vocabularies) can be super helpful and are not complicated to build.
Example
The mean return to a portfolio is the weighted average return of the stocks making up the portfolio.
Let’s say a portfolio consists of 30% GOOG shares with a mean daily return of 0.14% and 70% MSFT shares, mean daily return of 0.03%.
The mean daily return is:
(0.3 * .14) + (0.7 * 0.03) = 0.063
Another portfolio of 50% GOOG and 50% MSFT gives
(0.5 * .14) + (0.5 * 0.03) = 0.085
The PowerShell DSV
I’d like to represent the portfolio like the following, legal PowerShell syntax.
Portfolio 'Tech Companies' { New-Stock GOOG .3 New-Stock MSFT .7}
Portfolio 'Tech Companies Balanced' { New-Stock GOOG .5 New-Stock MSFT .5}
Let’s build up the Domain Specific Vocabulary
Lines 1-3 enable the DSV to work and prints:
Tech Companies Tech Companies Balanced
1: Function Portfolio ($portFolioName, [scriptBlock] $sb) {
2: $portFolioName
3: }
4:
5: Portfolio 'Tech Companies' {
6: New-Stock GOOG .3
7: New-Stock MSFT .7
8: }
9:
10: Portfolio 'Tech Companies Balanced' {
11: New-Stock GOOG .5
12: New-Stock MSFT .5
13: }
Adding lines 4-8 will output the snippet below. Note line 7 uses “&”, the PowerShell call operator, to evaluate the script block.
Tech Companies GOOG .3 MSFT .7 Tech Companies Balanced GOOG .5 MSFT .5
1: Function Portfolio ($portFolioName, [scriptBlock] $sb) {
2: $portFolioName
3:
4: Function New-Stock ($stockName, $percentage) {
5: "`t$stockName $percentage"
6: }
7:
8: & $sb
9: }
Transform the Data into objects
Let’s transform the data into objects with properties so it prints the following table, with the added plus of addressable properties.
PortFolioName Stock Percentage------------- ----- ----------Tech Companies GOOG .3Tech Companies MSFT .7Tech Companies Balanced GOOG .5Tech Companies Balanced MSFT .5
1: Function Portfolio ($portFolioName, [scriptBlock] $sb) {
2: Function New-Stock ($stockName, $percentage) {
3: New-Object PSObject | Select @{
4: Name = "PortFolioName"
5: Expression = {$portFolioName}
6: }, @{
7: Name = "Stock"
8: Expression = {$stockName}
9: }, @{
10: Name = "Percentage"
11: Expression = {$percentage}
12: }
13: }
14:
15: & $sb
16: }
Calculate the Weighted Average
Adding a hash table lookup in lines 4-7 and the properties MeanDailyReturn and WeightedAverage in lines 18-24.
Lines 20 and 23 look up the MeanDailyReturn by stock name using dot notation.
PortFolioName Stock Percentage MeanDailyReturn WeightedAverage------------- ----- ---------- --------------- ---------------Tech Companies GOOG .3 0.14 0.042Tech Companies MSFT .7 0.03 0.021Tech Companies Balanced GOOG .5 0.14 0.07Tech Companies Balanced MSFT .5 0.03 0.015
1: Function Portfolio ($portFolioName, [scriptBlock] $sb) {
2:
3: Function New-Stock ($stockName, $percentage) {
4: $MeanDailyReturn = @{
5: GOOG = .14
6: MSFT = .03
7: }
8:
9: New-Object PSObject | Select @{
10: Name = "PortFolioName"
11: Expression = {$portFolioName}
12: }, @{
13: Name = "Stock"
14: Expression = {$stockName}
15: }, @{
16: Name = "Percentage"
17: Expression = {$percentage}
18: }, @{
19: Name = "MeanDailyReturn"
20: Expression = {$MeanDailyReturn.$stockName}
21: }, @{
22: Name = "WeightedAverage"
23: Expression = {$MeanDailyReturn.$stockName * $percentage}
24: }
25: }
26:
27: & $sb
28: }
In an upcoming post
The transformation of the DSV into objects and properties is finished. In an upcoming post we’ll add some more detail and play with the output.