Skip to content

Commit

Permalink
Update `RandomCartesianModelGenerator.getRandomCandlestickLayerModelP…
Browse files Browse the repository at this point in the history
…artial`
  • Loading branch information
patrickmichalik committed Apr 14, 2024
1 parent 09a5c85 commit 03d7cc8
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package com.patrykandpatrick.vico.core.cartesian.data

import androidx.annotation.RestrictTo
import com.patrykandpatrick.vico.core.common.length
import com.patrykandpatrick.vico.core.common.random
import kotlin.random.Random

Expand Down Expand Up @@ -48,39 +49,45 @@ public object RandomCartesianModelGenerator {
openingClosingRange: ClosedFloatingPointRange<Float> = defaultOpeningClosingRange,
lowHighRange: ClosedFloatingPointRange<Float> = defaultLowHighRange,
): CandlestickCartesianLayerModel.Partial {
var previousOpeningPrice: Float? = null
var previousClosingPrice: Float? = null
val opening = mutableListOf<Float>()
val closing = mutableListOf<Float>()
val low = mutableListOf<Float>()
val high = mutableListOf<Float>()
val maxOpeningPriceDelta = .2f * openingClosingRange.length
val changeOverrideThreshold = .2f * openingClosingRange.length
val maxClosingPriceDelta = .8f * openingClosingRange.length
for (i in x) {
val isBullish = Random.nextBoolean()
val openingPrice: Float
val closingPrice: Float
if (isBullish) {
openingPrice =
if (previousOpeningPrice != null && previousClosingPrice != null) {
floatArrayOf(previousOpeningPrice, previousClosingPrice).random().coerceIn(openingClosingRange)
val openingPrice =
if (previousClosingPrice != null) {
previousClosingPrice +
Random.nextFloat() *
if (Random.nextBoolean()) {
(openingClosingRange.endInclusive - previousClosingPrice).coerceAtMost(maxOpeningPriceDelta)
} else {
(openingClosingRange.start - previousClosingPrice).coerceAtLeast(-maxOpeningPriceDelta)
}
} else {
openingClosingRange.random()
}
val isBullish =
when {
openingPrice - openingClosingRange.start < changeOverrideThreshold -> true
openingClosingRange.endInclusive - openingPrice < changeOverrideThreshold -> false
else -> Random.nextBoolean()
}
val closingPrice =
openingPrice +
Random.nextFloat() *
if (isBullish) {
(openingClosingRange.endInclusive - openingPrice).coerceAtMost(maxClosingPriceDelta)
} else {
y.random().coerceIn(openingClosingRange)
(openingClosingRange.start - openingPrice).coerceAtLeast(-maxClosingPriceDelta)
}
closingPrice = (openingPrice + lowHighRange.random())
} else {
closingPrice =
if (previousOpeningPrice != null && previousClosingPrice != null) {
floatArrayOf(previousOpeningPrice, previousClosingPrice).random().coerceIn(openingClosingRange)
} else {
y.random().coerceIn(openingClosingRange)
}
openingPrice = (closingPrice + lowHighRange.random())
}
opening += openingPrice
closing += closingPrice
low += minOf(openingPrice, closingPrice) - lowHighRange.random()
high += maxOf(openingPrice, closingPrice) + lowHighRange.random()

previousOpeningPrice = openingPrice
previousClosingPrice = closingPrice
}
return CandlestickCartesianLayerModel.partial(x.toList(), opening, closing, low, high)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,9 @@ internal fun Float.gcdWith(other: Float): Float =
internal fun <T : Comparable<T>> T.isBoundOf(range: ClosedFloatingPointRange<T>) =
this == range.start || this == range.endInclusive

internal fun ClosedFloatingPointRange<Float>.random(): Float = start + (endInclusive - start) * Random.nextFloat()
internal val ClosedFloatingPointRange<Float>.length get() = endInclusive - start

internal fun ClosedFloatingPointRange<Float>.random() = start + Random.nextFloat() * length

internal fun Int.getDivisors(includeDividend: Boolean = true) =
buildList {
Expand Down

0 comments on commit 03d7cc8

Please sign in to comment.