理解和转换 ThinkScripts CompoundValue 函数
Understanding & Converting ThinkScripts CompoundValue Function
我目前正在将 ThinkScript 指示器转换为 C#,但是,我已经 运行 到这个 CompoundValue
函数中,但我不确定如何转换它。
文档内容如下:
Calculates a compound value according to following rule: if a bar
number is greater than length then the visible data value is returned,
otherwise the historical data value is returned. This function is used
to initialize studies with recursion.
使用示例:
declare lower;
def x = CompoundValue(2, x[1] + x[2], 1);
plot FibonacciNumbers = x;
我的解读:
基于描述和示例。看来我们正在 x[1] + x[2]
中传递一个计算,它在当前柱和前一个柱上执行此计算(基于 2
的第一个参数)。我不确定参数 1
的用途。
我的问题:
请解释这个函数的实际作用。如果可能,请使用伪代码说明此方法的工作原理。
请让我提供 thinkscript 本身代码的两个等效工作版本。我们使用这种方法通过将等效输出彼此相减来证明等效性 - 结果应为 0.
# The original Fibonacci code with a parameter "length" added.
# That parameter is the first parameter of the CompoundValue function.
declare lower;
def length = 2;
def x = CompoundValue(length, x[1] + x[2], 1);
# plot FibonacciNumbers = x;
# Equivalent code using the `if` statement:
def y;
if(BarNumber() > length){
# Visible data. This is within the guarded branch of the if statement.
# Historical data y[1] (1 bar back) and y[2] (2 bars back) is available
y = y[1] + y[2];
}else{
# Not enough historical data so we use the special case satisfying the
# original rule.
y = 1;
}
plot FibonacciNumbersDiff = y - x;
Thinkscript "recursion" 是一个有点夸张的术语。函数名称 CompoundValue
不是很有用,因此可能会造成混淆。
使用if
语句的版本通常更有用,因为在遍历时间序列的柱时,我们经常需要一个包含多个嵌套if
语句的程序结构——这是做不到的使用 CompoundValue
函数。请参阅我在扫描上下文中使用它的其他文章。
在Java中,使用相同的结构,看起来是这样的:
int size = 100;
int length = 2;
int[] values = new int[size];
for(int index = 1; index < size; index++){
if(index > length){
values[index] = values[index - 1] + values[index - 2];
}else{
values[index] = 1;
}
}
根本区别在于 for
循环,它在 thinkscript 代码中不存在。 thinkscript 以一种控制反转的方式提供循环,它多次执行用户代码,每个柱执行一次。
对于 TLDR; crowd,一些简单的代码,希望可以解释 CompoundValue()
函数正在尝试做什么,这可能有助于转换它的功能:
# from: Chapter 12. Past/Future Offset and Prefetch
# https://tlc.thinkorswim.com/center/reference/thinkScript/tutorials/Advanced/Chapter-12---Past-Offset-and-Prefetch
# According to this tutorial, thinkScript uses the highest offset, overriding
# all lower offsets in the script - WOW
declare lower;
# recursive addition using x[1] is overridden by 11 in the plot for
# Average(close, 11) below; SO `x = x[1] + 1` becomes `x = x[11] + 1`
def x = x[1] + 1;
# using CompoundValue, though, we can force the use of the *desired* value
# arguments are:
# - length: the number of bars for this variable's offset (`1` here)
# - "visible data": value to use IF VALUES EXIST for a bar (a calculation here)
# - "historical data": value to use IF NO VALUE EXISTS for a bar (`1` here)
def y = CompoundValue(1, y[1] + 1, 1);
# *plotting* this Average statement will change ALL offsets to 11!
plot Average11 = Average(close, 11);
# `def`ing the offset DOES NOT change other offsets, so no issue here
# (if the `def` setup DID change the offsets, then `x[1]` would
# become `x[14]`, as 14 is higher than 11. However, `x[1]` doesn't change.
def Average14 = Average(close, 14);
plot myline = x;
plot myline2 = y;
# add some labels to tell us what thinkScript calculated
def numBars = HighestAll(BarNumber());
AddLabel(yes, "# Bars on Chart: " + numBars, Color.YELLOW);
AddLabel(yes, "x @ bar 1: " + GetValue(x, numBars), Color.ORANGE);
AddLabel(yes, "x @ bar " + numBars + ": " + x, Color.ORANGE);
AddLabel(yes, "y @ bar 1: " + GetValue(y, numBars), Color.LIGHT_ORANGE);
AddLabel(yes, "y @ bar " + numBars + ": " + y, Color.ORANGE);
现在,一些,呃,很多细节...
首先,关于“偏移”值的快速说明:
thinkScript 与其他交易相关语言一样,使用内部循环系统。这就像一个 for
循环,遍历图表上的所有“周期”或“柱”(例如,日线图上 1 柱 = 1 天;1 分钟盘中图表上 1 柱 = 1 分钟, ETC)。 thinkScript 中的每一行代码都是 运行,用于图表中的 每个柱 或脚本中指定的时间长度。
如 OP 所述,x[1]
表示循环正在处理的当前柱 之前 一个柱的偏移量。 x[2]
表示当前柱之前的两个柱,依此类推。此外,可以使用负数抵消未来:例如,x[-1]
表示当前柱线 领先 一根柱线。
这些偏移量与 C# 中的 for
循环类似,只是它们是反向的:C# 中的 x[0]
表示当前的 x
值,就像在 thinkScript 中一样;但是,在循环中向前移动,x[1]
将是 下一个 值,而 x[-1]
将不存在,因为在 0 之前没有过去的值.(当然,一般来说!在 C# 中肯定可以使用负数循环。重点是 thinkScript 中的正偏移索引表示 过去 柱,而 thinkScript 中的负偏移索引表示 future bars - 在 C# 中不是这样。)
此处同样重要的是“长度”的概念:在 thinkScript 中,length
参数表示您想要移动的距离 - 就像偏移量一样,但是是一个范围而不是一个特定的柱。在我上面的示例代码中,我使用了语句 plot Average11 = Average(close, 11);
在这种情况下,11
参数表示绘制 11 个柱的收盘价,即偏移 x[0]
到 x[10]
.
现在,解释 CompoundValue() 函数的用途:
Chapter 12. Past/Future Offset and Prefetch thinkScript 教程解释了 thinkScript 实际上 覆盖 脚本中具有最大值的较小偏移或长度值。这意味着如果你有两个项目定义如下:
def x = x[1] + 1;
plot Average11 = Average(close, 11);
thinkScript 实际上会用 Average 语句中使用的较长长度覆盖 x[1]
偏移量 - 因此导致 x[1]
变为 x[11]
!
哎呀!这意味着指定的偏移量(最高偏移量除外)对 thinkScript 没有任何意义!那么,等一下 - 有 对所有内容都使用相同的偏移量吗?不!这就是 CompoundValue() 发挥作用的地方...
同一章解释了 CompoundValue() 允许为变量指定偏移量 ,即使存在更高的偏移量也不会更改。
带有参数标签的 CompoundValue() 函数看起来像这样:
CompoundValue(length, "visible data", "historical data")
正如 OP 指出的那样,这并不是特别清楚。以下是参数代表的内容:
length:此变量的偏移柱数。
在我们的示例中,def x = x[1] + 1
,有 1 个小柱偏移量,因此我们的语句以 CompoundValue(length=1, ...)
开头。相反,如果它是一个更大的偏移量,比如 14 个柱,我们将放置 CompoundValue(length=14, ...)
“可见数据”:thinkScript 应该执行的值或计算if DATA IS AVAILABLE for the current bar .
同样,在我们的示例中,我们使用 x[1] + 1
的计算,因此 CompoundValue(length=1, "visible data"=(x[1] + 1), ...)
。 (等式周围的括号不是必需的,但可能有助于清楚。)
“历史数据”:使用的值如果当前柱没有数据可用。
在我们的示例中,如果没有可用数据,我们将使用值 1
。
现在,在 thinkScript 中,如果参数按顺序 and/or 提供默认值,则不需要参数标签。所以,我们可以这样写这个 CompoundValue 语句 没有 标签:
def y = CompoundValue(1, y[1] + 1, 1);
或者像这样 和 标签:
def y = CompoundValue(length=1, "visible data"=(y[1] + 1), "historical data"=1);
(请注意,包含空格的参数名称必须用双引号括起来。单字参数名称不需要引号。另外,为了清楚起见,我在等式周围放置了括号;这不需要。)
总结:需要 CompoundValue(...) 来确保变量使用系统 (thinkScript) 中实际需要的 offset/number 柱,否则 覆盖指定的偏移量(如果存在)。
如果脚本中的所有偏移量都相同,或者如果使用不同的编程系统,则 CompoundValue() 可以简单地分解为其适当的计算或值,例如 def x = x[1] + 1
或者,或者,一个 if/else
语句,在需要的任何柱或条件下填写所需的值。
我目前正在将 ThinkScript 指示器转换为 C#,但是,我已经 运行 到这个 CompoundValue
函数中,但我不确定如何转换它。
文档内容如下:
Calculates a compound value according to following rule: if a bar number is greater than length then the visible data value is returned, otherwise the historical data value is returned. This function is used to initialize studies with recursion.
使用示例:
declare lower;
def x = CompoundValue(2, x[1] + x[2], 1);
plot FibonacciNumbers = x;
我的解读:
基于描述和示例。看来我们正在 x[1] + x[2]
中传递一个计算,它在当前柱和前一个柱上执行此计算(基于 2
的第一个参数)。我不确定参数 1
的用途。
我的问题:
请解释这个函数的实际作用。如果可能,请使用伪代码说明此方法的工作原理。
请让我提供 thinkscript 本身代码的两个等效工作版本。我们使用这种方法通过将等效输出彼此相减来证明等效性 - 结果应为 0.
# The original Fibonacci code with a parameter "length" added.
# That parameter is the first parameter of the CompoundValue function.
declare lower;
def length = 2;
def x = CompoundValue(length, x[1] + x[2], 1);
# plot FibonacciNumbers = x;
# Equivalent code using the `if` statement:
def y;
if(BarNumber() > length){
# Visible data. This is within the guarded branch of the if statement.
# Historical data y[1] (1 bar back) and y[2] (2 bars back) is available
y = y[1] + y[2];
}else{
# Not enough historical data so we use the special case satisfying the
# original rule.
y = 1;
}
plot FibonacciNumbersDiff = y - x;
Thinkscript "recursion" 是一个有点夸张的术语。函数名称 CompoundValue
不是很有用,因此可能会造成混淆。
使用if
语句的版本通常更有用,因为在遍历时间序列的柱时,我们经常需要一个包含多个嵌套if
语句的程序结构——这是做不到的使用 CompoundValue
函数。请参阅我在扫描上下文中使用它的其他文章。
在Java中,使用相同的结构,看起来是这样的:
int size = 100;
int length = 2;
int[] values = new int[size];
for(int index = 1; index < size; index++){
if(index > length){
values[index] = values[index - 1] + values[index - 2];
}else{
values[index] = 1;
}
}
根本区别在于 for
循环,它在 thinkscript 代码中不存在。 thinkscript 以一种控制反转的方式提供循环,它多次执行用户代码,每个柱执行一次。
对于 TLDR; crowd,一些简单的代码,希望可以解释 CompoundValue()
函数正在尝试做什么,这可能有助于转换它的功能:
# from: Chapter 12. Past/Future Offset and Prefetch
# https://tlc.thinkorswim.com/center/reference/thinkScript/tutorials/Advanced/Chapter-12---Past-Offset-and-Prefetch
# According to this tutorial, thinkScript uses the highest offset, overriding
# all lower offsets in the script - WOW
declare lower;
# recursive addition using x[1] is overridden by 11 in the plot for
# Average(close, 11) below; SO `x = x[1] + 1` becomes `x = x[11] + 1`
def x = x[1] + 1;
# using CompoundValue, though, we can force the use of the *desired* value
# arguments are:
# - length: the number of bars for this variable's offset (`1` here)
# - "visible data": value to use IF VALUES EXIST for a bar (a calculation here)
# - "historical data": value to use IF NO VALUE EXISTS for a bar (`1` here)
def y = CompoundValue(1, y[1] + 1, 1);
# *plotting* this Average statement will change ALL offsets to 11!
plot Average11 = Average(close, 11);
# `def`ing the offset DOES NOT change other offsets, so no issue here
# (if the `def` setup DID change the offsets, then `x[1]` would
# become `x[14]`, as 14 is higher than 11. However, `x[1]` doesn't change.
def Average14 = Average(close, 14);
plot myline = x;
plot myline2 = y;
# add some labels to tell us what thinkScript calculated
def numBars = HighestAll(BarNumber());
AddLabel(yes, "# Bars on Chart: " + numBars, Color.YELLOW);
AddLabel(yes, "x @ bar 1: " + GetValue(x, numBars), Color.ORANGE);
AddLabel(yes, "x @ bar " + numBars + ": " + x, Color.ORANGE);
AddLabel(yes, "y @ bar 1: " + GetValue(y, numBars), Color.LIGHT_ORANGE);
AddLabel(yes, "y @ bar " + numBars + ": " + y, Color.ORANGE);
现在,一些,呃,很多细节...
首先,关于“偏移”值的快速说明:
thinkScript 与其他交易相关语言一样,使用内部循环系统。这就像一个 for
循环,遍历图表上的所有“周期”或“柱”(例如,日线图上 1 柱 = 1 天;1 分钟盘中图表上 1 柱 = 1 分钟, ETC)。 thinkScript 中的每一行代码都是 运行,用于图表中的 每个柱 或脚本中指定的时间长度。
如 OP 所述,x[1]
表示循环正在处理的当前柱 之前 一个柱的偏移量。 x[2]
表示当前柱之前的两个柱,依此类推。此外,可以使用负数抵消未来:例如,x[-1]
表示当前柱线 领先 一根柱线。
这些偏移量与 C# 中的 for
循环类似,只是它们是反向的:C# 中的 x[0]
表示当前的 x
值,就像在 thinkScript 中一样;但是,在循环中向前移动,x[1]
将是 下一个 值,而 x[-1]
将不存在,因为在 0 之前没有过去的值.(当然,一般来说!在 C# 中肯定可以使用负数循环。重点是 thinkScript 中的正偏移索引表示 过去 柱,而 thinkScript 中的负偏移索引表示 future bars - 在 C# 中不是这样。)
此处同样重要的是“长度”的概念:在 thinkScript 中,length
参数表示您想要移动的距离 - 就像偏移量一样,但是是一个范围而不是一个特定的柱。在我上面的示例代码中,我使用了语句 plot Average11 = Average(close, 11);
在这种情况下,11
参数表示绘制 11 个柱的收盘价,即偏移 x[0]
到 x[10]
.
现在,解释 CompoundValue() 函数的用途:
Chapter 12. Past/Future Offset and Prefetch thinkScript 教程解释了 thinkScript 实际上 覆盖 脚本中具有最大值的较小偏移或长度值。这意味着如果你有两个项目定义如下:
def x = x[1] + 1;
plot Average11 = Average(close, 11);
thinkScript 实际上会用 Average 语句中使用的较长长度覆盖 x[1]
偏移量 - 因此导致 x[1]
变为 x[11]
!
哎呀!这意味着指定的偏移量(最高偏移量除外)对 thinkScript 没有任何意义!那么,等一下 - 有 对所有内容都使用相同的偏移量吗?不!这就是 CompoundValue() 发挥作用的地方...
同一章解释了 CompoundValue() 允许为变量指定偏移量 ,即使存在更高的偏移量也不会更改。
带有参数标签的 CompoundValue() 函数看起来像这样:
CompoundValue(length, "visible data", "historical data")
正如 OP 指出的那样,这并不是特别清楚。以下是参数代表的内容:
length:此变量的偏移柱数。
在我们的示例中,
def x = x[1] + 1
,有 1 个小柱偏移量,因此我们的语句以CompoundValue(length=1, ...)
开头。相反,如果它是一个更大的偏移量,比如 14 个柱,我们将放置CompoundValue(length=14, ...)
“可见数据”:thinkScript 应该执行的值或计算if DATA IS AVAILABLE for the current bar .
同样,在我们的示例中,我们使用
x[1] + 1
的计算,因此CompoundValue(length=1, "visible data"=(x[1] + 1), ...)
。 (等式周围的括号不是必需的,但可能有助于清楚。)“历史数据”:使用的值如果当前柱没有数据可用。
在我们的示例中,如果没有可用数据,我们将使用值
1
。
现在,在 thinkScript 中,如果参数按顺序 and/or 提供默认值,则不需要参数标签。所以,我们可以这样写这个 CompoundValue 语句 没有 标签:
def y = CompoundValue(1, y[1] + 1, 1);
或者像这样 和 标签:
def y = CompoundValue(length=1, "visible data"=(y[1] + 1), "historical data"=1);
(请注意,包含空格的参数名称必须用双引号括起来。单字参数名称不需要引号。另外,为了清楚起见,我在等式周围放置了括号;这不需要。)
总结:需要 CompoundValue(...) 来确保变量使用系统 (thinkScript) 中实际需要的 offset/number 柱,否则 覆盖指定的偏移量(如果存在)。
如果脚本中的所有偏移量都相同,或者如果使用不同的编程系统,则 CompoundValue() 可以简单地分解为其适当的计算或值,例如 def x = x[1] + 1
或者,或者,一个 if/else
语句,在需要的任何柱或条件下填写所需的值。