首页 > 解决方案 > 用于技术分析指标的 Kotlin

问题描述

我想将Kotlin 用于技术分析框架,因为我在 java 代码中有几个额外的库。我将计划扩展引擎来计算指标和策略。

例如,目前在某些策略的条件下使用简单移动平均线:

if (EMA(C, 24) > MA(L, 100)) { ... }

因此,指数移动平均线和标准移动平均线有两个指标(函数)。必须从收盘价和低价(它是一些标准的双值系列)计算,长度为 24 和 100。

这种直接包含指标的条件对于框架的最终用户来说非常好,我想保持这种风格!

现在的问题:例如,这个带有指标的条件是一些策略代码的一部分。但这部分代码是按价格条计算的。这意味着每个价格值的多次。指标有自己的历史,可以使用一些额外的上下文,用于额外的配置或数据。理想状态是,EMA(C, 24) 函数表达式必须与指标的特定对象/实例绑定,该指标不是单例但属于该表达式,因为有一些历史记录、添加的上下文等。但我不想创建外部对象!必须保留条件示例的结构。或者在函数中使用一些函数,可以注入上下文或附加数据,并保留一些历史记录。主要问题是这条线是针对每个柱子执行的,它不仅仅是一次调用,而是这个条件的增量调用。

Kotlin 为函数、lambdas、对象提供了许多可能性。我正在尝试为这种类型的用例找到一些最佳解决方案,一方面是快速/良好的性能,另一方面是良好的条件编写。

感谢您的帮助和想法。

标签: algorithmkotlindesign-patterns

解决方案


如果您不想创建单独的类,可以尝试使用 lambdas 从主类传递值:

typealias averageAlg = (a: String, b: Int, history: MutableList<Int>) -> Int
class AverageClass(var emaAlg: averageAlg, var maAlg: averageAlg) {

    private val historyEma = ArrayList<Int>() // for store configuration
    private val historyMa = ArrayList<Int>()

    fun calculation() {
        if (EMA("C", 20) < MA("L", 100)) {} else {}
    }
    // the names of your functions will remain unchanged.
    private fun EMA(a: String, b: Int): Int = emaAlg(a, b, historyEma)
    private fun MA(a: String, b: Int): Int = maAlg(a, b, historyMa)
}

定义可以改变的算法。例如:

val emaAlg: averageAlg = { a, b, historyEma ->
    val calcValue = a.length + b
    historyEma.add(calcValue) // modify history
    println(historyEma)
    calcValue // return current value
}
...
val averageClass = AverageClass(emaAlg, maAlg)
averageClass.calculation()

变体 2。或者您可以创建单独的类:

class EMA(private var emaF: averageAlg) {
    val list = ArrayList<Int>() // for store configuration
    fun f(a: String, b: Int): Int = emaF(a, b, list)
}

class MA(private var maF: averageAlg) {
    val list = ArrayList<Int>() // for store configuration
    fun f(a: String, b: Int): Int = maF(a, b, list)
}

val ema = EMA { a, b, history ->
    // here your algorithm
}

val ma = MA { a, b, history ->
    // here your algorithm
}
if (ema.f("C", 24) < ma.f("L", 100)) { ... }

推荐阅读