Technical Analysis Indicator Library
Overview
Provides a wrapper around the talib-ruby library which is a ruby wrapper for the ta-lib library.
This library has been designed to make interfacing with the ta-lib functions easy by wrapping each function in a ruby class.
The wrappers are autogenerated from the xml function description provided with the ta-lib project.
Usage
Requires the talib-ruby gem. The examples require the yahoofinance gem.
Install via gem using:
gem install ta-indicator
Simple Example
The easiest way to use the indicator library is to include the indicator mixin module. This module extends the Array class with the Indicator::Mixin module allowing quick calculations to be performed:
require 'indicator/mixin'
data = [1, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3]
results = data.indicator(:sma, :time_period => 5)
results = data.indicator(:sma, 5)
results = data.indicator(:sma_5)
All perform a simple moving average with time period of 5 and produce the same results:
=> [nil, nil, nil, nil, 2.2, 2.4, 2.6, 2.4, 2.6, 2.4, 2.6]
More complex indicators can also be used
result = data.indicator(:macd_12_26_9)
This performs a macd calculation using a slow period of 12, fast period of 26 and signal period of 9.
The list of available indicators can be retrieved via
Indicator.list
Information about each indicator including a list of arguments can be retrieved via:
Indicator.info :sma
Inficator.info :macd
...
Details
The base Indicator functions are located in the Indicator module and the auto generated classed are located in the Indicator::AutoGen module. All of the following examples assume these modules have been included:
require 'indicator'
include Indicator
include Indicator::AutoGen
Class Construction
All ta-lib functions are wrapped in a class named using the camel class name of the function: SMA is Sma, AVGPRICE is AvgPrice, etc. The constructor takes the optional arguments either as a hash or argument list. For example the Macd class takes three arguments, fast_period, slow_period and signal_period. They can be initialised in any of the following ways:
sma = Sma.new 5
macd = Macd.new 12,26,9
or
sma = Sma.new :time_period => 5
macd = Macd.new :fast_period => 12, :slow_period => 26, :signal_period => 9
If a parameter is not passed in then it will be initialised to the default value as specified by the ta-lib interface.
The Indicator module also supports factory style functions to simplify class creation.
sma = Indicator.create :sma
sma = Indicator.create :sma, 5
sma = Indicator.create :sma, time_period => 5
macd = Indicator.create :macd
macd = Indicator.create :macd, 12,26,9
macd = Indicator.create :macd, :fast_period => 12, :slow_period => 26, :signal_period => 9
If a indicator is to be constructed using only integer parameters then an indicator can be constructed using the create_named factory function. The create_named function expects the indicator name optionally followed by it’s arguments joined by an underscore.
sma = Indicator.create_named :sma_5
macd = Indicator.create_named :macd_12_26_9
Argument attributes
All arguments can be updated through attributes:
macd.fast_period
=> 12
macd.slow_period = 30
=> 30
A list of all the arguments that a particular class takes can be be retrieved using the class method ‘arguments’.
Macd.arguments
=> [:fast_period, :slow_period, :signal_period]
Sma.arguments
=> [:time_period]
Running The Indicators
Each indicator defines a run method that takes in each input array to be processed as a List. An example of an indicator that takes one input:
sma = Indicator.create_named :sma_5
sma.run [1,2,3,4,3,2,3,2,3,2,3,2]
=> [nil, nil, nil, nil, 2.6, 2.8, 3.0, 2.8, 2.6, 2.4, 2.6, 2.4]
An example of an indicator that takes two inputs:
add = Indicator.create_named :add
add.run [1,2,3,4,5], [5,4,3,2,1]
=> [6.0, 6.0, 6.0, 6.0, 6.0]
Some indicators require OHLC (and optionally V) price inputs. An example of an indicator that takes price inputs:
avg = AvgPrice.new
# AvgPrice run function takes open, high, low, close
avg.run [1,2,1,2], [2,1,2,1], [3,1,3,1], [1,3,1,3]
=> [1.75, 1.75, 1.75, 1.75]
A list of inputs that a indicator run function requires can be retrieved using the class method ‘inputs’.
Sma.inputs
=> [:in_real]
Add.inputs
=> [:in_real0, in_real1]
AvgPrice.inputs
=> [:open, :high, :low, :close]
AdOsc.inputs
=> [:open, :high, :low, :close, :volume]
Outputs
The run function returns an array containing the results if there is only one List to return otherwise it returns a hash that maps each output List to it’s name. For eample:
sma = Sma.new(5)
sma.run [1,2,3,4,3,2,3,2,3,2,3,2]
=> [nil, nil, nil, nil, 2.6, 2.8, 3.0, 2.8, 2.6, 2.4, 2.6, 2.4]
macd = Macd.new 3,4,1
result = macd.run [1,2,3,4,4,3]
puts results[:out_macd]
=> [nil, nil, -3.785768566076978e-270, 0.5, nil, nil]
puts result[:out_macd_signal]
=> [nil, nil, 0.399999999999999, 0.189999999999999, nil, nil],
puts result[:out_macd_hist]
=> [nil, nil, -0.3999999999999999, 0.31000000000000005, nil, nil]
A list of outputs that an indicator run function returns can be retrieved using the class method ‘outputs’.
Sma.outputs
=> [:out_real]
Macd.outputs
=> [:out_macd, :out_macd_signal, :out_macd_hist]
Data Mapping
The run function also accepts a DataMapping::Map structure which can be used to extract data from an enumerable collection.
# Assume historical_data is a list of hashes with the following keys
# :open, :high, :low, :close, :volume
sma = Sma.new 5
sma_results = sma.run(DataMapper::Map.new(historical_data, :open))
When the above example is run the DataMapper will attempt to extract data from the historical_data collection by either calling a function called open or retrieving a hash value using the key :open. You can also directly pass in a lambda function if a more complex mapping function is required. To reduce the amount of code required a helper function called new_map is available:
sma = Sma.new 5
sma_results = sma.run new_map(historical_data, :open)
sma_results = sma.run new_map(historical_data, lambda => |b| { b[:open] / 2 })
By default the run function will attempt to use a default getter of :open, so the following is also valid:
sma = Sma.new 5
sma_results = sma.run historical_data
# Calculates the sma by accessing [:open] on each element of historical_data
The default getter can be changed:
sma = Sma.new 5
sma.default_getter :high
sma_results = sma.run historical_data
# Calculates the sma by accessing [:high] on each element of historical_data
The same mapping system works for functions requiring price data as an input. The AvgPrice function can be called using either of the following syntax:
ap = AvgPrice.new
ap.run(
new_map(historical_data, :open),
new_map(historical_data, :high),
new_map(historical_data, :low),
new_map(historical_data, :close))
or
ap = AvgPrice.new
ap.run historical_data
The run function will again attempt to use sensible default mappings of :open, :high, :low, :close and :volume (if required).
Regenerating the wrappers
The wrappers can be regenerated using the gen_wrapper.rb file in the tools directory:
ruby gen_wrapper.rb
This script must be run from the tools directory as it uses realtive paths. The gen_wrapper.rb script uses the erb library to generate code from the defined templates.
Copyright
Copyright © 2012 Michael Lamb. See LICENSE for details.
The files ta_func_api.xml and ta_func_api.xsd are from the talib library. The license details are contained within LICENSE-ta-lib.