通达信DLL公式编写和内置函数公式是两条路径。内置函数由客户端直接实现,写进公式就能算;外部函数要先有一个动态链接库,再由公式引擎在运行时按名称去装载并调用。两条路径的差别不在写法复杂程度,而在依赖链的长度——后者多了一个必须存在的文件。
下面按「差别、声明、约束、对应关系、排查」的顺序讲。全文只讲公式与文件的对接方式,不涉及任何品种判断,也不评价公式算出来的数值是否有意义。文中提到的函数名与装载细节以通达信公式编辑器内附的函数说明为准,不同版本对动态库的支持范围可能不同。
一、外部函数接进来之后,公式引擎多了什么动作
普通公式的计算全程在客户端内部完成。接上外部函数之后,引擎的处理顺序变成:读到一处外部函数声明,按声明找到对应的动态库,把参数传进去,把返回值接回公式变量。这个过程对公式作者是透明的,但它在运行期引入了新的失败点。
{ 通达信DLL公式编写:调用关系示意 }
公式源码
└─ 声明一处外部函数(以字符串形式书写函数名)
└─ 公式引擎按名称装载动态库
└─ 参数按序列传入 → 返回值回填到公式变量
{ 链条上任何一环缺失,公式的输出就会变成空值 }
看清这条链之后,排查的方向也就确定了:先确认声明写对,再确认动态库能被找到,最后确认参数与返回值对得上。这三点按顺序查,比反复改公式源码有效。
二、公式里怎么声明外部函数
外部函数在公式源码里以一个字符串常量出现,字符串的内容与动态库里导出的函数名对应。它与普通变量赋值的写法相近,区别在于右侧是带引号的名称,而不是一个算式。
声明位置在公式的开头部分,也就是输出语句之前。多条外部函数各自写一行,名称不能重复。写完声明之后,公式里的其他语句就可以像使用普通函数那样使用它,参数按顺序写在括号里。
| 位置 | 写什么 | 写错的后果 |
|---|---|---|
| 声明行 | 与动态库导出名一致的字符串 | 名称对不上,装载失败,输出为空 |
| 参数位置 | 按库内定义的顺序与个数传入 | 个数或顺序不符,返回结果无意义 |
| 输出位置 | 把返回值赋给一个公式变量 | 没有赋值,后续语句取不到结果 |
三、位数与依赖:两处容易被漏掉的约束
通达信DLL公式编写里最先出问题的位置不在公式源码,而在动态库本身的两项属性。
第一项是位数。动态库有32位与64位两种形态,客户端也有。两者位数不一致时,装载在第一步就失败,公式不会报出具体的编译错误,只会输出空值。核对办法是查看客户端主程序的文件属性,与动态库的位数对照,两者必须一致。
第二项是依赖。动态库本身可能还需要别的运行库才能装载,这些依赖没有随包提供时,装载同样失败。核对办法是把动态库单独放到一个临时目录,尝试用系统自带的装载方式打开它,缺哪个依赖会直接提示出来。
{ 装载失败的三种表现与对应的方向 }
找不到库文件 → 路径或文件名不对,先确认库放到了引擎能搜索的位置
位数不匹配 → 库与客户端位数不一致,重新编译或换用匹配的版本
缺少依赖库 → 库本身能读,但它依赖的运行库不在,补齐依赖即可
{ 这三种都不是公式源码的问题,改源码不会有效果 }
四、参数与返回值怎么对应
外部函数的参数以序列形式传入:公式里的一列数据对应库函数的一个参数位,库函数返回的结果再变成公式里的一列。理解这一点之后,参数个数不符与返回长度不符这两类问题就容易定位了。
以行情序列作为输入时,输出长度与输入长度一致。如果库函数的返回值长度与输入不一致,引擎在拼接结果时会出现错位,表现是数值整体偏移若干根。核对办法是把公式的输出与一个已知序列(比如收盘价)画在同一副图,看偏移是否固定:偏移固定说明长度对不上,逐根随机说明参数顺序有问题。
参数的数据类型也需要对上。价格、成交量与自定义参数在库函数里可能对应不同的数据形态,把成交量传给一个期望价格的参数位,库里算得出来,结果却没有意义。核对办法是先用一个简单参数单独调用一次,确认返回值符合库函数的说明,再逐步加上其余参数。
五、编译通过但输出为空的排查顺序
这一类问题的特点是公式保存成功、编译无提示,挂上去之后输出是空的或是一条平直线。排查按链条顺序走,每一步只判断一件事。
- 把公式里除声明之外的内容全部去掉,只输出一个常数,确认公式本身能显示。
- 把常数换成调用外部函数的那一行,参数先只给一个,看是否出值。
- 出值之后逐个补齐参数,补齐到某一步开始不出值,问题就落在那个参数上。
- 始终不出值,回到第二节核对声明字符串与库内导出名是否逐字符一致。
公式在编辑状态下保存成功,与它在运行期能装载动态库,是两件事。编辑只检查语法,装载发生在计算时,所以编译通过不代表调用链完整。这一点也解释了为什么同一份公式换一台机器就失效:动态库没有跟着走。
六、把使用范围限定在可控的范围内
外部函数的能力来自动态库,而不来自公式语言。这意味着三件事需要自己确认清楚:库的来源是否可追溯、库在目标机器上是否具备装载条件、以及库被替换之后公式的输出是否仍然可比。
第三点尤其要注意。同一份公式,底下的动态库换了版本,输出可能变化,而这种变化在公式源码里看不出来。给公式做记录时,把库的名称、版本与取得时间一并记下,输出的数值才有参照。这部分记录建议与 公式安装与导入 一栏里的导入记录放在一起,公式与它依赖的文件成对留存。
如果编译或挂载环节出现提示,先按提示原文分类再动手改,提示的读法可以对照 公式报错与卡顿排查 一栏。日常只需要内置函数就能完成的写法,则在 公式编写教程 一栏里按语法分类整理。
通达信DLL公式编写的边界,落在「可控」两个字上:公式源码可控、参数可控,但动态库是一个外部文件,它的存在、位数与版本都需要单独管理。把这三项记进公式台账,外部函数这条路才是可复用的;少了这几项记录,它只是一次性的实验结果。
文中涉及的动态库装载机制、声明写法与参数传递方式为通用技术口径;通达信各版本对动态库的接口约定、函数名清单与支持范围可能不同,具体的函数签名与调用方式请以你所用版本公式编辑器内的函数说明与官方技术资料为准。
