Turbine and .streck
Capture your project’s finances with Turbine — powered by the intuitive and expressive .streck language.
The turbine software and the .streck language are available for macOS, Linux and Windows. (We are on version 1.1.)
MacOS
To download a signed and notarized installation program for macOS, click here.
A signed and notarized installation guarantees that the software has been
verified by Apple for the absence of malicious components and confirmed as
untampered. Upon installation, the turbine binary is placed in
/usr/local/bin.
Linux
To download the Turbine program for Linux,
click here. Download, gunzip the
file and place the binary in /usr/local/bin.
Windows
To download the Turbine program for Windows, click here. The Windows binary is signed.
Welcome to turbine and the .streck
language — your powerful toolkit for modeling, proving, and
explaining the dynamics of complex financial scenarios. Whether you are
working on interactions between companies, families, or other
entities, Turbine helps you bring clarity, precision, and confidence to your
financial reasoning.
Tutorial
The streck language is a language with statements, expressions and functions, concepts familiar for everyone who programmed in a computer language, for example Java or Go. The streck language however has one feature up its sleeve: The traditional programming concepts can coexist with a fourth construct: transactions. A transaction is a timestamped sequence of statements, a record of something not only referenced by a line number, but referenceable by its point in time as well. Transactions can be sorted by your computer and since it contains statements it can be executed by your computer as part of a simulation.
Let us have a look at what a hello world program written in streck looks like:
/* helloworld.streck | illustrating streck and transactions. */
2025-07-14 11:00:00 print 'is this sorted correctly?\n'
2025-07-14 08:00:00 print 'Hello world 🤝 starting simulation.\n'
2025-07-14 17:00:00 print 'simulation end.\n'
To run the example, write turbine helloworld.streck at your
prompt. Your console should look something like
prompt> turbine helloworld.streck
Hello world 🤝 starting simulation.
is this sorted correctly?
simulation end.
prompt>
Note that we do not have a procedure as in 'hello world' programs written
in other computer languages, but that three transactions are sorted and
that statements can be executed. Let us now look at a second more detailed
example. Before doing so, however, let us first discuss what a
key-value store is. A key-value store is a type of database
that stores data as a collection of key-value pairs. The key is a unique
identifier used to retrieve the associated value and the value can in
general terms be anything - text, numbers, binary data. In turbine the
'value' is an entity or a time-series. Back to our second example, this
time we want to record variations in time for an entity named
Company1. We also want to look back on our data and compute
a summary and output the result on the terminal. We write the following:
/* retrospect.streck | illustrating entity, time series and summation. */
2024-12-31 23:59:59
print 'Retrospect 🤝 starting simulation.\n'
entity Company1 named 'My Company'
account Company1.A1920 named 'Bank account'
account Company1.A3010 named 'Domestic sales of goods'
2025-07-14 13:56:26
bookkeep Company1 {
debit A1920 with 25000.00
credit A3010 with 25000.00
} comment 'A change in A1920 and A3010.'
2025-12-31 23:59:59
var result = SumYearCredit(Company1,A3010) -
SumYearDebit(Company1,A3010)
print 'The yearly result is: \(result)\n'
print 'simulation end.\n'
In the example above we create an entity Company1, we define two
time series A1920 and A3010, we record a variation
on two accounts and we can look back on the change, assign the yearly sale to
a local variable and output the sum to the terminal. When executed, the code
outputs:
Retrospect 🤝 starting simulation.
The yearly result is: 25000.00
simulation end.
In .streck, we want to write readable code that is easy to
understand so the language supports functions, a concept that is useful for
two purposes: (1) To capture a parameterized sequence of statements that that
can be reused from one or many transactions, and (2) to compute a value that
is part of an expression. The first case is in computer science sometimes
called a procedure and the second case is called a function.
In .streck, we can add a procedure anywhere in a
.streck file — even after its first use in a transaction.
The normal way is to have the procedures at the beginning of a
.streck file or in a separate file included from the command line.
Since we have a very short program, we add the procedure to the beginning of
the file as in
/* coherence.streck | illustrating procedures. */
func Sale(priceInclVat) /* ⬷ a procedure. */
{
bookkeep Company1 {
debit A1920 with priceInclVat
credit A3010 with priceInclVat
} comment 'Interacting with customer.'
}
2024-12-31 23:59:59
print 'Coherence 🤝 starting simulation.\n'
entity Company1 named 'My Company'
account Company1.A1920 named 'Bank account'
account Company1.A3010 named 'Domestic sales of goods'
2025-07-14 13:56:26 Sale(25000.00)
2025-07-14 15:56:26 Sale(25000.00)
2025-12-31 23:59:59
var result = SumYearCredit(Company1,A3010) -
SumYearDebit(Company1,A3010)
print 'The yearly result is: \(result)\n'
print 'simulation end.\n'
The program outputs:
Coherence 🤝 starting simulation.
The yearly result is: 50000.00
simulation end.
As with procedures, a function can be defined anywhere in a
.streck file or in a file included from the command
line:
/* compliance.streck | illustrating procedures and functions. */
func Gold(ounces, pricePerOunce) /* ⬷ a function. */
{
return ounces * pricePerOunce
}
func SaleAndPayment_Gold(ounces, priceInclVat₋per₋ounce) /* ⬷ a procedure. */
{
var priceExclVat = 0.8 * Gold(ounces,priceInclVat₋per₋ounce)
var priceInclVat = 1.25 * priceExclVat
bookkeep Company1 {
debit A1510 with priceInclVat
credit A2611 with priceInclVat - priceExclVat
credit A3010 with priceExclVat
} comment 'Sale Gold'
bookkeep Company1 {
credit A1510 with priceInclVat
debit A1920 with priceInclVat
} comment 'Payment Gold'
}
2024-12-31 23:59:59
print 'Compliance 🤝 starting simulation.\n'
entity Company1 named 'My Company'
account Company1.A1510 named 'Accounts Receivable'
account Company1.A1920 named 'Bank account'
account Company1.A2611 named 'Output VAT'
account Company1.A3010 named 'Domestic sales of goods'
2025-07-14 13:56:26 SaleAndPayment_Gold(10, 3384.49)
2025-07-15 15:43:12 SaleAndPayment_Gold(10, 3373.38)
/* ⬷ the parameters are 'ounces' followed by 'price per ounce'. */
2025-12-31 23:59:59
var yearlyResult = SumYearCredit(Company1,A3010) -
SumYearDebit(Company1,A3010)
var assetsCash = SumYearDebit(Company1,A1920) -
SumYearCredit(Company1,A1920)
print 'The result is: \(yearlyResult)\n'
print 'The accumulation is: \(assetsCash)\n'
print 'simulation end.\n'
This example gives us the sum:
Compliance 🤝 starting simulation.
The result is: 54062.96
The accumulation is: 67578.70
simulation end.
In the example above, we have four accounts, one function, and one procedure.
Using the defined procedure SaleAndPayment_Gold, we can record both
the sale of goods and the corresponding payment. We also output two values:
yearlyResult and assetsCash, the latter representing
accumulated funds expected to be carried forward to the daybook for future years.
We have now seen streck examples for documenting sales and purchases. We can also use turbine to compute the monthly Vat as in the following example:
/* consistent.streck | VAT is closing the month. */
func SalesGoods25(priceExclVat)
{
var priceInclVat = 1.25 * priceExclVat
bookkeep Company1 {
debit A1510 with priceInclVat
credit A2611 with priceInclVat - priceExclVat
credit A3010 with priceExclVat
} comment 'Sale goods 25%.'
}
func ExpenseSnowClearance(priceInclVat) {
var priceExclVat = 0.8 * priceInclVat
bookkeep Company1 {
debit A5164 with priceExclVat
debit A2641 with priceInclVat - priceExclVat
credit A2440 with priceInclVat
} comment 'Expense snow clearance.'
}
func MonthlyVat() {
var salesVat = SumMonthCredit(Company1,A2611)
var purchaseVat = SumMonthDebit(Company1,A2641)
bookkeep Company1 {
debit A2611 with salesVat
credit A2650 with salesVat
credit A2641 with purchaseVat
debit A2650 with purchaseVat
} comment 'VAT January 2025'
print 'The sales Vat is: \(salesVat)\n'
print 'The purchase Vat is: \(purchaseVat)\n'
}
2024-12-31 23:59:59
print 'Consistent 🤝 starting simulation.\n'
entity Company1 named 'My Company'
account Company1.A1510 named 'Accounts receivable'
account Company1.A2440 named 'Accounts payable'
account Company1.A2611 named 'Output VAT'
account Company1.A2641 named 'Input VAT (Recoverable)'
account Company1.A2650 named 'VAT payable/receivable'
account Company1.A3010 named 'Domestic sales of goods'
account Company1.A5164 named 'Snow-clearance'
2025-01-14 13:56:26 SalesGoods25(25000.00)
2025-01-14 13:56:26 ExpenseSnowClearance(18750.00)
2025-01-31 23:59:59 MonthlyVat()
2025-12-31 23:59:59
print 'simulation end.\n'
In this example we close the month with a computation on A2611,
A2650, and A2641. The program outputs
Consistent 🤝 starting simulation.
The sales Vat is: 6250.00
The purchase Vat is: 3750.00
simulation end.
So we finish the month by writing out the values to report to a tax agency.
Additional Details on .streck
In this section, facets of the .streck language are described.
We look at reserved words, the available predefined functions and other
details.
Keywords
The streck language has fourteen plus five plus three keywords. A keyword has a special meaning in streck and can not be used as an identifier for a function, procedure, entity, or time series.
account
credit
entity
named
var
bookkeep
debit
func
print
with
comment
else
if
return
Five additional keywords are defined to construct transaction sequences:
ending
interval
occurring
schedule
starting
And three keywords are reserved for handling change in accounting method:
before
end
do
A transaction sequence is by turbine ended before
ending in case the ending is defined and before last
transaction in case ending is not specified.
How to use the keywords are described in the Tutorial section in this document.
Predeclared Names
Eight functions are predeclared in streck: SumYearDebit,
SumYearCredit, SumMonthDebit,
SumMonthCredit, SumDayDebit,
SumDayCredit, SumAllDebit,
SumAllCredit. Each function accepts an entity identifier as its first argument and a time series key as its second argument.
Identifiers
An identifier in streck is a Unicode token that does not begin with a digit.
Command-Line Usage
You can specify multiple .streck files as arguments when running
turbine from the command line as in
prompt> turbine definition.streck daybook-2025-and-closing.streck
All transactions from the provided files are aggregated, sorted in
chronological order, and then executed. Prior to execution, all definitions
are collected and made available for use within the transactions.
Revision Handling and .streck
Your streck files are UTF-8 encoded text files. This means your work can be tracked with for example the Git revision handling system.