kotlinplotchartslets-plot

How to use 2 colors on same line lets-plot in kotlin?


I have a trading chart. I wanna have a segment where a stock was purchased and where it was not.

data:

What I expect to see: enter image description here

Currently, I draw 10 geomLine charts here:

... 

    var chart = letsPlot(data)
    chart += geomLine(
        color = "dark-green",
        tooltips = TooltipOptions().title("$ticker cost"),
        mapping = {
            x = "x"
            y = "y"
        }
    )


    repeat(isPurchased.size) {
        chart += drawRedChart(it)
    }

    private fun drawRedChart(index: Int): Feature {
        return geomLine(
            color = "red",
            mapping = {
                x = "x$index"
                y = "y$index"
            }
        )
    }

This solution works, but it takes too much memory and I duplicate lists for each segment where a stock was purchased, so, my solution is bad and non-optimal.

Could you help draw a line based on the cost list with 2 colors, where RED means purchased and GREEN is not purchased, as shown in the screenshot above using Kotlin?

UPD: Tried

val history = intArrayOf(10,11,12,13,14,15,14,13,12,11,10,11,12,14,15,18,20,19,14,14)
val isPurchased = listOf(false, false, false, true, true, true ,true,true,false,false,false,false,false,false,false,false,false,false,false,false)
val steps = List(history.size) { it }

val data = mutableMapOf<String, Any>()
data["x"] = steps
data["y"] = history 

var chart = letsPlot(data)
chart += geomLine(
    tooltips = layerTooltips().title("$ticker cost"),
    mapping = {
        x = "x"
        y = "y"
        color = isPurchased
    }
)

chart += scaleColorManual(listOf("red", "dark-green"), limits = listOf(true, false))

But this code makes wrong behavior with some gaps and the green line should be terminated when the red one started: enter image description here

Any ideas on how to fix it?


Solution

  • Lets-plot supports variadic colors on line and path geometries. Try just one line where the color is mapped to the "isPurchased" variable:

    geomLine(
            tooltips = layerTooltips().title("$ticker cost"), // <-- also better
            mapping = {
                x = "x"
                y = "y"
                color = "isPurchased"
            }
    

    You will also need to setup a red/green color scale for this mapping:

    + scaleColorManual(listOf("red", "green"), limits = listOf(false, true))
    

    See also: Variadic lines demo.

    UPD: sorry for confusion. Indeed, the solution above will split one line in two lines because true/false values are treated as discrete values which is resulted in creation of two groups of points.

    To fix this try to encode true/false as numeric values like 1 and 0. Accordingly, the scale will be:

    + scaleColorManual(listOf("red", "green"), limits = listOf(0, 1))