我的需求是尽量减少策略中的变量和逻辑数量, 将和独立因子相关的变量和操作尽量封装在一个独立的用户函数里面。在文档中没有找到相关的详细说明, 于是试了一下:
用户函数(getVal):
Vars
Series<Numeric> val;
Begin
// 简化演示, 当前的收盘价作为最新的Val数值, 具体实现中可能是MA\标准差或者其他更复杂的逻辑
val = Close;
// 返回用户函数内部存储的变量前一个数值, 这里就是前一天的收盘价
Return val[1];
End
策略:
Params
Vars
Series<Numeric> lastVal;
Events
OnBar(ArrayRef<Integer> indexs)
{
Numeric lastVal= getVal();
PlotNumeric("lastVal", lastVal);
}
从结果看, 确实图表输出了上一个收盘价。但是从一般编程语言习惯思考,getVal()中的 Series<Numeric> val似乎是一个函数内部的局部变量。这种使用方式似乎在编程语言一般习惯上是错误的。但是结果却是正确的。如果这种调用是对的,似乎是用户函数中的序列变量绑定到了Bar上面,每个Bar对于每次用户函数调用使用和策略内相同的变量存储逻辑。
所以问题如下:
1。 请问这种做法是合法的吗?还是一种类似于未定义的行为?
2。 能否麻烦提供定义序列变量在用户函数中作为Vars的合法使用方式文档( 用户函数的文档: https://tbq3.tbquant.net/helper?product_id=991&keyword=440&content_id=262&selectedkey=3827&type=article , 没有看到关于这种用法的特别说明. )
谢谢
没听懂你的意思。所谓的合不合法是合哪个法?
函数中的series类型当然是函数内部的,否则不是很容易跟外部的容器重名吗
另外每个函数在每一根bar上都是有自己独立空间的,这才能够做到函数内部的series类型可以回溯调取。
当然如果你对数据结构有更好的建议可以提出来,我会转发给产品研发人员看看适不适合。
合法当然是符合TB的语法。
不是建议, 我只是没有查到: 在用户函数中, 使用Series类型变量的文档和具体解释。
想确认这种行为是否符合TB的语法,因为从一般编程习惯上用户函数的变量看起来像是函数内部的变量。也不可能看到咱们的源码实现逻辑,所以如果文档找不到,所以只能去猜测,比如如下的C++函数,变量vec在每次调用方法foo时都是会重新声明的局部变量,函数返回后就会销毁,里面的数值不再可用。
void foo(){
Vector<int> vec;
vec.push(...);
return vec[1];
}
但是在我帖子的用法里的结果看,val并不是一个函数内部的局部变量,更像一个绑定到了Bar数据的全局变量。这里实际会引申出来一些其他的担忧,比如:如果在策略中不同行使用不同参数重复调用这个用户函数,这时新的调用也会覆盖旧的调用中的变量,好像是会有问题的。
如果说“函数中的series类型当然是函数内部的”那么和我问题中的测试结果似乎是矛盾的,从那个结果看来,似乎用户函数内部的Series的存储空间是全局绑定到Bar上的,并且没有被销毁。