如何开发自定义指标
OpenQuant offers a possibility to develop custom user indicators and use such user indicators in OpenQuant strategy.
OpenQuant提供了开发自定义用户指标和在OpenQuant策略中使用这些指标的功能。
You can develop a custom indicator as a dll in MS Visual Studio and add to OpenQuant as a reference. You can exchange your custom indicators with another OpenQuant users this way (without need to disclose indicator code if you don’t want to). Alternatively, you can add indicator code right before strategy code in OpenQuant editor and use it in this strategy.
你能在MSVS中开发一个自定义指标dll并把它以链接形式加入OpenQuant。你能以这种方式同别的OpenQuant用户交换你自定义的指标(如果你不愿意公开代码就不需要公开)。 或者,直接在OpenQuant编辑器的策略代码前编写指标代码,并在这个策略中使用指标。
In order to start writing a user indicator you should add
为了开始编写一个用户指标,你需要增加如下代码:
Any user indicator should derive from the UserIndicator class defined in the OpenQuant.API.Plugins namespace.
- using OpenQuant.API.Plugins;
任何用户指标都继承UserIndicator类,它在OpenQuant.API.Plugins命名空间中定义。
Developing a user indicator in the OpenQuant framework is quite simple. All you need to do is to override the Calculate(int index) method of the UserIndicator class using Input property of UserIndicator class.
在OpenQuant框架中开发一个用户指标是很简单的。 你所需要做的就是覆写UserIndicator类的Calculate(int index),并利用到Input属性。
The Input property is a reference to indicator input time series. It has ISeries type, so that it can be BarSeries, TimeSeries or another Indicator (this way you can develop indicator of indicator).
Input属性是指标输入时间序列的引用。它具有ISeries接口,即可以是BarSeries, TimeSeries或是其它指标(这样你能开发指标的指标)。
The Calculate(int index) method should return indicator value calculated for the index-th element in the Input series. It should return Double.NaN if there is no indicator value for the index-th element of the Input series (usually in case of indicators that require several past values of Input time series, for example simple moving average or momentum indicators).
Calculate(int index)应该返回由Input类型中指定索引元素计算得出的指标值。 如果没有值,就返回Double.NaN(通常是由于指标需要Input时间序列过去的几个值,例如简单移动平均线或者惯性指标)。
Let’s develop a simple Accumulated Money Flow (AMF) indicator as an example. The simplest formula will be making an upday volume negative and a down day volume positive and then adding up all the buy/sell volume from date from which the data became available.
我们开发一个简单的AMF(累计货币流量)指标为例。 最简单的方法是在上涨日记交易量为正,在下跌日记交易量为负,然后将交易量累加。(译者注:原文将上涨与下跌下反了)
We create a new class that we call AMF and derive this class from UserIndicator class. Then we add a constructor of AMF class that takes BarSeries as input.
Note that we use the Name property of te UserIndicator class to give a name to our indicator. This name will be displayed on the Bar chart and elsewhere.
- public class AMF: UserIndicator
{
public AMF(BarSeries input) : base(input)
{- Name = “AMF”;
- }
- }
注意:我们使用了UserIndicator类的Name属性,这个名字会在Bar图表和其他地方显示。
Now if we write
现在如果我们编写下列代码
in our strategy, we will create an AMF indicator called “AMF” and Input property assigned to the Bars series of our strategy.
- AMF indicator = new AMF(Bars);
在我们的策略中,我们创建了一个指标叫做AMF,然后给Input属性分配Bars序列。
Now we need to override the Calculate method of our AMF indicator.
现在,我们需要覆写AMF指标中的Calculate。
Note that we can use two techniques to work with the Input property. We can either cast it to a specific series type and use this type in our calculations, for example
- public class AMF: UserIndicator
- {
- double volume = 0;
public AMF(BarSeries input) : base(input)
{
Name = “AMF”;
}
public override double Calculate(int index)
{
if (index > 1)
{
if (Input[index, BarData.Close] > Input[index-1, BarData.Close])
volume += Input[index, BarData.Volume];
else
volume -= Input[index, BarData.Volume];
return volume;
}
else
return Double.NaN;
}
}
注意:我们有2种方法来使用Input属性。可以转换成特殊类型,然后在计算中使用,例如
or we can use common indexers of ISeries interface.
- BarSeries bars = Input as BarSeries;
double close = bars[index].Close;
或者我们能使用公共的ISeries接口的索引器。
We use the latter techniques in our Calculation method.
- double close = Input[index, BarData.Close];
在这我们在Calculation中使用第二种方法。
The rest of Calculate code is quite simple. First we check that we have enough elements in the Input series to access previous element (bar) of the Input series. We return Double.NaN if there is no previous bar. If we do have a previous bar, we compare closing prices of the current (index) bar and previous (index - 1) bar and then adjust volume class variable accordingly.
剩下的Calculate代码是很简单的。首先,我们检查我们在Input系列中是否有足够的之前的元素(bar)。 如果没有之前的bar,就返回Double.NaN。如果有,我们就比较当前(index)bar和之前(index-1)bar的最新的价格,从而调整交易量类型的变量。
Now we can add our indicator to a strategy and draw it on the strategy bar chart.
现在我们能把我们的指标添加到策略中并把它画到策略bar图表。
Note that there are several other examples of user indicators included in the OpenQuant installation. They can be found in the Samples folder in OpenQuant Windows menu.
- using System;
- using System.Drawing;
using OpenQuant.API;
using OpenQuant.API.Indicators;
using OpenQuant.API.Plugins;
public class AMF: UserIndicator
{
double volume = 0;
public AMF(BarSeries input) : base(input)
{
Name = “AMF”;
}
public override double Calculate(int index)
{
if (index > 1)
{
if (Input[index, BarData.Close] > Input[index-1, BarData.Close])
volume += Input[index, BarData.Volume];
else
volume -= Input[index, BarData.Volume];
return volume;
}
else
return Double.NaN;
}
}
public class MyStrategy : Strategy
{
public override void OnStrategyStart()
{
AMF AMF = new AMF(Bars);
AMF.Color = Color.White;
Draw(AMF, 2);
}
public override void OnBar(Bar bar)
{
}
}
注意:在OpenQuant安装目录还有其他几个用户指标的示例。能在OpenQuant目录下Samples文件夹中找到它们。