Menu

Tree [r7] /
 History

HTTPS access


File Date Author Commit
 autom4te.cache 2006-08-05 tbandrow [r1] Initial Build
 debug 2006-08-13 tbandrow [r7] Added automated unit testing for skip list and ...
 html 2006-08-05 tbandrow [r1] Initial Build
 latex 2006-08-05 tbandrow [r1] Initial Build
 optimized 2006-08-05 tbandrow [r1] Initial Build
 retired 2006-08-05 tbandrow [r1] Initial Build
 src 2006-08-13 tbandrow [r7] Added automated unit testing for skip list and ...
 templates 2006-08-05 tbandrow [r1] Initial Build
 xml 2006-08-05 tbandrow [r1] Initial Build
 AUTHORS 2006-08-05 tbandrow [r1] Initial Build
 COPYING 2006-08-05 tbandrow [r1] Initial Build
 ChangeLog 2006-08-05 tbandrow [r1] Initial Build
 Doxyfile 2006-08-05 tbandrow [r1] Initial Build
 INSTALL 2006-08-05 tbandrow [r1] Initial Build
 Makefile.am 2006-08-05 tbandrow [r1] Initial Build
 Makefile.cvs 2006-08-05 tbandrow [r1] Initial Build
 Makefile.in 2006-08-05 tbandrow [r1] Initial Build
 NEWS 2006-08-05 tbandrow [r1] Initial Build
 README 2006-08-05 tbandrow [r1] Initial Build
 TODO 2006-08-05 tbandrow [r1] Initial Build
 aclocal.m4 2006-08-05 tbandrow [r1] Initial Build
 config.guess 2006-08-05 tbandrow [r1] Initial Build
 config.h.in 2006-08-05 tbandrow [r1] Initial Build
 config.sub 2006-08-05 tbandrow [r1] Initial Build
 configure 2006-08-05 tbandrow [r1] Initial Build
 configure.in 2006-08-05 tbandrow [r1] Initial Build
 depcomp 2006-08-05 tbandrow [r1] Initial Build
 garrett.kdevelop 2006-08-13 tbandrow [r4] Added orderedList and other classes in support ...
 garrett.kdevelop.pcs 2006-08-06 tbandrow [r3] Fixed blow up on parse. garrett would blow up ...
 garrett.kdevses 2006-08-06 tbandrow [r3] Fixed blow up on parse. garrett would blow up ...
 garrett.tag 2006-08-05 tbandrow [r1] Initial Build
 install-sh 2006-08-05 tbandrow [r1] Initial Build
 ltmain.sh 2006-08-05 tbandrow [r1] Initial Build
 missing 2006-08-05 tbandrow [r1] Initial Build
 mkinstalldirs 2006-08-05 tbandrow [r1] Initial Build
 tags 2006-08-05 tbandrow [r1] Initial Build

Read Me

----------------------------------------------
GARRETT
A Financial Systems Evaluation Language
(c) 2006 Todd Bandrowsky 
All Rights Reserved
----------------------------------------------

Horizons is a tool for asking questions about complex portfolios. It lets you
specify a set of time series curves, associate them with a collection
of contracts, and then, Spel will iterate through as many combinations
of them as you are interested in to help you better understand your
portfolio.

* Flexible iteration.  Create scenarios, for example, that
  explore various price ranges by season and all of
  their combinations.

* Horizons handles temporal situations readily.  
  You specify to Horizons your rules at a series
  level, and Horizons quantizes them into discrete
  time series chunks as needed to run the simulation.

* Horizons handles curves easily.  Roll hourly data to 
  monthly easily, extract by various custom defined masks, 
  and more.

* Horizons is fairly optimized and will only be optimized more.  
  Horizons's number crunching is multithreaded.  With 
  important sections hand coded in AMD64 assembly language,
  Horizons takes advantage of the both extended 
  SSE2 and GP registers afforded by that hardware.  We're 
  also working on a POWER architecture port.  We will use
  Altivec on PowerPC 970MP and on POWER5 when available.

* Horizons is easy.  You tell Horizons what you want, 
  and it figures out how to do it.  

A Basic Horizons Scenario
-----------------------
simulation name="Market Forecast" {

	curverange name = "henry hub", interpolations = 5 {
		from  intervalCurve( 'monthly', '5/1/2005', 42, 12, 24, 33, 17, 18, 19, 20 ),
		to  intervalCurve( 'monthly', '5/1/2005',  5, 8, 6, 77, 22, 33, 55, 55 )
	}

	curverange name = "pjm whub", interpolations = 7 {
		from  intervalCurve( 'monthly', '5/1/2005', 42, 12, 24, 33, 17, 18, 19, 20 ),
		to  intervalCurve( 'monthly', '5/1/2005',  5, 8, 6, 77, 22, 33, 55, 55 )
	}
	
	curverange name = "zoot", interpolations = 7 {
		from intervalCurve( 'monthly', '5/1/2005', 42, 12, 24, 33, 17, 18, 19, 20 ) * .90,
		to fromcurve * 1.10
	}

 	curverange name = "zoot", interpolations = 7 {
		from intervalCurve( 'monthly', '5/1/2005', 42, 12, 24, 33, 17, 18, 19, 20 ) * .90,
		to fromcurve * 1.10
	}

	model name = "spark generator" {
		parameters {
			curve PowerPrice,
			curve FuelPrice,
			curve HeatRate,	
			curve OandM
		}
		outputs {
			value
		}
		state name = "idle", start = (powerCurve < (FuelCurve * HeatRate + OandM)) =
		{
			remaining {
				value = -OandM;
			}
		}
		state name = "running", start = (powerCurve > (FuelCurve * HeatRate + OandM)) =
		{
			remaining {
				value = powerCurve - (FuelCurve * HeatRate + OandM);
			}
		}
	}

	contract id="CTR0042", name="Fossil Bird 1", model="spark generator" {
		PowerPrice = "pjm whub",
		FuelPrice = "henry hub",
		HeatRate = intervalCurve( 'monthly', '5/1/2005',  5, 8, 6, 77, 22, 33, 55, 55 ),
		OandM = intervalCurve( 'monthly', '5/1/2005',  5, 8, 6, 77, 22, 33, 55, 55 )
	}

	contract id="CTR0043", name="Fossil Bird 2", model="spark generator", start="5/1/2005", stop="6/1/2005" {
		PowerPrice = "pjm whub",
		FuelPrice = "henry hub",
		HeatRAte = intervalCurve( 'monthly', '5/1/2005',  5, 8, 6, 77, 22, 33, 55, 55 ),
		OandM = intervalCurve( 'monthly', '5/1/2005',  5, 8, 6, 77, 22, 33, 55, 55 )
	}
}

Horizons Overview
-------------
A basic Horizons scenario has a simulation outermost block, a set of curves, 
a set of models, and then a list of contracts.  The contracts compare 
roughly to business contracts in the real world and each contract refers
to a model that describes how to calculate it.

Curves are ranges of time series data.  Each curve has a from series 
and a to series, both starting at the "start" date declared in the curve, 
and, having the same number of data points spaced by the "interval" length.

When Horizons runs a scenario, it loops through all the permutations of the 
interpolations of the curves.  That is, if I have a single curve, with 
interpolations set to 5, then, I will get 5 simulations.  If I have two curves
with interpolations set to 5, and 4, respectively, 
I will get 20 simulations.

Each simulation's curves are then fed, as needed, into the contract engine.
Each contract refers to a particular model, via the "model" tag in its line,
and also parameters to be fed into the model unique to that contract.

A model has with it a list of states.  States allow the rules of the model 
to change with particular circumstances in such a way as that they may 
be tracked.  You might think of a state as an "if then with a name".

For each discrete interval in each simulation, Spel evaluates the states 
of each contract, and chooses the state which matches the conditional.  
The contract is then evaluated at that state, and both the output values and
the state are recorded at each interval for subsequent analysis.

Explaining the Example
----------------------
This simple example models a very simplified set of generator contracts 
for an electric utility.

In the electricity world, a benchmark way to determine the profitability of 
a generator is to look at its spark spread.  The generator is modelled 
as a vehicle for converting a fuel price into a power price.  Thus, 
the expression powerCurve > FuelCurve * HeatRate + OandM, the spark spread, 
models the profitability of the generator.  If the power price is greater 
than the fuel price times the cost to convert it, plus some fixed 
O and M cost, the generator is profitable and it enters the running state. 
If not, then, the generator is in the idle state.  There, it can only costs, 
so its value is negative.

Sample Curves
-------------
We define a basic price curve for fuel and for power.  We declare, in the top 
of the simulation, curves for power using "PJM W Hub" and the natural gas price 
index "Henry Hub".  In the real world, these prices would be gleaned from various 
forecasting tools available to the industry.  In this example, I made them up.

When Horizons runs a scenario, it steps through different sets of curves.  Each curve
iterated through is called a curverange.

	curverange name = "henry hub", interpolations = 5 {
		from  intervalCurve( 'monthly', '5/1/2005', 42, 12, 24, 33, 17, 18, 19, 20 ),
		to  intervalCurve( 'monthly', '5/1/2005',  5, 8, 6, 77, 22, 33, 55, 55 )
	}

	curverange name = "pjm whub", interpolations = 7 {
		from  intervalCurve( 'monthly', '5/1/2005', 42, 12, 24, 33, 17, 18, 19, 20 ),
		to  intervalCurve( 'monthly', '5/1/2005',  5, 8, 6, 77, 22, 33, 55, 55 )
	}


The interpolations of 5 for the "henry hub" mean that there will be 5 curves 
from the "from" curve to the "to" curve, and likewise, there are 7 curves to 
be generated for pjm whub.

Sample Model
------------
Next, we define a model.  A model defines shared logic to be used by contracts. 
If a contract is an instance of a class, then, a model would be the class itself.    

	model name = "spark generator" {
		parameters {
			curve PowerPrice,
			curve FuelPrice,
			curve HeatRate,	
			curve OandM
		}
		outputs {
			value
		}
		state name = "idle", start = (powerCurve < (FuelCurve * HeatRate + OandM))
		{
			remaining {
				value = -OandM;
			}
		}
		state name = "running", start = (powerCurve > (FuelCurve * HeatRate + OandM))
		{
			remaining {
				value = powerCurve - (FuelCurve * HeatRate + OandM);
			}
		}
	}
}

Models consist of states that are conditionally evaluated at each time
point over the span of the contract

Our model is called a "spark generator", short for spark spread generator.  
It takes 4 parameters, each of which is a curve.  The model outputs one series,
called value.  

The model has two states, "idle", and "running".  The conditional expression
assigned to each state's start parameter specifies when that state will be
valid.  

The remaining tag inside each state says specifies that the rule inside is
to be applied for all of the time spent in that state.  You can specify other
brackets as well.  In a more complex scenario, you may want to capture the
time needed to ramp up into that new state.  

		state name = "running", start = (powerCurve > (FuelCurve * HeatRate + OandM))
		{
			schedule name="rampup", time=4, units=hours {
				value = @counter * 10
			}
			remaining {
				value = spread;
			}
		}
}

A state is selected in a model only when the conditional is true.  Once a state
is selected, it will be evaluated for at least the time in each schedule section within 
a state.  Then, once the schedule advances to its remaining section, all of the states
are evaluated for every interval.

Special Variables
-----------------
You'll notice that there are some special variables that are being used in 
simulations. 

@counter - the number of intervals elapsed in that state
@percentage - the percentage completion of that state in a schedule slot
	Note that @percentage will always be 0 for a remaining section of a state
@elapsed - the elapsed time in the state

CurveBuilders
-------------
curves are defined either by entering them or by expression.  There are several ways
to make a curve.  The most common is the intervalCurve( ). For example:

intervalCurve( 'monthly', '5/1/2005', 42, 12, 24, 33, 17, 18, 19, 20 ),

Establishes a curve beginning at 5/1/2005, proceeding monthly through each of the values
associated with it: 5/1/2005 = 42, 6/1/2005 = 12, 7/1/2005 = 24, and so on.

Running the Simulation
------------------------
Spel compiles the simulation into AMD64 code.  
The generated code works in these steps:

1.  scan all the curves in the simulation and convert to the lowest
    common denominator interval length

2.  determine the schedule for each contract
    for each interval on the contract range, evaluate each of the start 
	clauses on for each contract in order and dump the schedule id to the 
	schedule table associated with each state

3.  for each interval on the schedule table for each state
	evaluate the state and update the result

4.  Merge the schedule results for all the intervals into
    a single schedule table

5.  Attach that schedule for each contract to the simulation

6.  The reporting phase then mines the simulation results

Implementation Note
-----------------------------------------------
Because GARRETT is a compiler, many classes are actually implemented as C structs with 
function calls so they can be more readilly accessed via assembler.

Optimizing Floating Point Expressions with SSE2
-----------------------------------------------
The floating point expressions, because they are executed so frequently, 
are heavily optimized.  This section describes how that optimization works.

Transformation - parallelizing constant expressions
-----------------------------------------------------
In general, siblings of any parse tree can be resolved in parallel.  

Consider the following infix expression:

powerCurve > FuelCurve * Heat Rate + OandM

We can build this dependency analysis:

A = FuelCurve * HeatRate
B = A + OandM
C = powerCurve > A

Clearly, in this case, there is not a lot that can be done in parallel. But,
what if, we did this?

powerCurve - OandM > FuelCurve * HeatRate

Then, we would have this set of twin items:

A0 = powerCurve - OandM
A1 = FuelCurve * HeatRate

Both of which could be executed in parallel


Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.