
Kotlin Multiplatform OHLCV/K-line chart components and primitives.
Kotlin Multiplatform OHLCV/K-line chart library built with Compose Multiplatform.
The library is host-app agnostic: it does not include exchange APIs, repositories, navigation, storage, trading models, or app themes. Those concerns are provided by the consuming app through configuration, formatters, overlays, markers, renderers, and custom panels.
commonMain.dependencies {
implementation("io.github.icyoung:kline-chart-kmp:0.1.3")
}The package root is:
import io.github.icyoung.KlineChartval dataState = rememberKlineChartDataState(initialCandles)
// Replace all data.
dataState.replaceAll(candles)
// Timestamp-based realtime update:
// - same timestamp as last candle: update last
// - greater timestamp: append
// - existing historical timestamp: replace existing
dataState.update(realtimeCandle)
KlineChart(
dataState = dataState,
config = KlineChartConfig(
chartStyle = ChartStyle.Candlestick,
pricePrecision = 2,
mainIndicators = setOf(MainIndicator.MA, MainIndicator.BOLL),
subIndicators = listOf(SubIndicator.MACD, SubIndicator.RSI, SubIndicator.WR, SubIndicator.OBV),
lastPriceMode = LastPriceMode.Latest,
crosshairDismiss = CrosshairDismiss.Persistent,
timeLabelFormatter = { timestamp -> timestamp.toString() },
),
colors = KlineChartColors(),
)See sample for Android, iOS, and Desktop apps backed by Binance public REST data. The sample uses a relative composite build and is not part of the published library.
KlineIndicator registration for main-chart overlays, existing sub-panel overlays, and new sub-panels.LastPriceMode.CrosshairDismiss.KlineChartDataState.KlineBuiltInIndicatorSpecs.KlineChart: top-level Compose chart.KlineChartConfig: layout, axes, indicators, precision, interaction, and overlay options.KlineChartColors: chart styling.KlineChartState: viewport and crosshair state for host synchronization.KlineChartDataState: list replacement, historical prepend, and timestamp-based realtime updates.KlineOverlayLine: generic price-level line and label.KlineHistoryMarker: above/below candle annotations.KlinePanelSpec: custom panel slot.KlineCustomIndicator: custom indicator calculation and drawing.KlineIndicator: reusable indicator formula abstraction for built-in and custom series.CandleRenderer: replaceable candle renderer.Use indicators for reusable formula-based indicators:
KlineChart(
dataState = dataState,
indicators = listOf(
klineIndicator(id = "MA120", pane = KlineIndicatorPane.Main, lookback = 120) { candles ->
listOf(KlineIndicatorLine("MA120", TechnicalIndicators.calculateMA(candles, 120) { it.close }))
},
klineIndicator(id = "MY_MACD_LINE", pane = KlineIndicatorPane.Sub, overlayId = "MACD") { candles ->
listOf(KlineIndicatorLine("X", candles.map { it.close }))
},
klineIndicator(id = "MY_PANEL", pane = KlineIndicatorPane.Sub, label = "MY") { candles ->
listOf(KlineIndicatorLine("C", candles.map { it.close }))
},
klineIndicator(
id = "BTC_MA20",
pane = KlineIndicatorPane.Main,
sourceCandles = btcCandles,
showLatestValue = true,
) { btc ->
listOf(KlineIndicatorLine("BTC MA20", TechnicalIndicators.calculateMA(btc, 20) { it.close }))
},
),
)pane = KlineIndicatorPane.Main: draw on the main chart.pane = KlineIndicatorPane.Sub with overlayId: draw on an existing sub-panel such as VOL, MACD, RSI, KDJ, WR, or OBV.pane = KlineIndicatorPane.Sub without overlayId: create a new sub-panel.sourceCandles: calculate the indicator from another candle stream and align it back to the chart candles by timestamp. It uses an independent hidden axis by default, so different price levels can be overlaid as trend lines. Use alignment = KlineIndicatorAlignment.Index for index-based alignment, or scaleMode = KlineIndicatorScaleMode.SharedPriceAxis when the values should share the main price axis.showLatestValue = true: show the indicator's latest visible value with the same dashed line and right-side label behavior as the latest price overlay.Implementation packages under io.github.icyoung.internal.* are not stable API.
From this directory:
./gradlew compileCommonMainKotlinMetadata
./gradlew desktopTestSample checks:
./gradlew -p sample :shared:compileCommonMainKotlinMetadata
./gradlew -p sample :androidApp:compileDebugKotlin
./gradlew -p sample :desktopApp:compileKotlin
./gradlew -p sample :shared:linkDebugFrameworkIosSimulatorArm64iOS sample:
xcodebuild -project sample/iosApp/iosApp.xcodeproj \
-scheme iosApp \
-configuration Debug \
-sdk iphonesimulator \
-destination 'generic/platform=iOS Simulator' \
buildKotlin Multiplatform OHLCV/K-line chart library built with Compose Multiplatform.
The library is host-app agnostic: it does not include exchange APIs, repositories, navigation, storage, trading models, or app themes. Those concerns are provided by the consuming app through configuration, formatters, overlays, markers, renderers, and custom panels.
commonMain.dependencies {
implementation("io.github.icyoung:kline-chart-kmp:0.1.3")
}The package root is:
import io.github.icyoung.KlineChartval dataState = rememberKlineChartDataState(initialCandles)
// Replace all data.
dataState.replaceAll(candles)
// Timestamp-based realtime update:
// - same timestamp as last candle: update last
// - greater timestamp: append
// - existing historical timestamp: replace existing
dataState.update(realtimeCandle)
KlineChart(
dataState = dataState,
config = KlineChartConfig(
chartStyle = ChartStyle.Candlestick,
pricePrecision = 2,
mainIndicators = setOf(MainIndicator.MA, MainIndicator.BOLL),
subIndicators = listOf(SubIndicator.MACD, SubIndicator.RSI, SubIndicator.WR, SubIndicator.OBV),
lastPriceMode = LastPriceMode.Latest,
crosshairDismiss = CrosshairDismiss.Persistent,
timeLabelFormatter = { timestamp -> timestamp.toString() },
),
colors = KlineChartColors(),
)See sample for Android, iOS, and Desktop apps backed by Binance public REST data. The sample uses a relative composite build and is not part of the published library.
KlineIndicator registration for main-chart overlays, existing sub-panel overlays, and new sub-panels.LastPriceMode.CrosshairDismiss.KlineChartDataState.KlineBuiltInIndicatorSpecs.KlineChart: top-level Compose chart.KlineChartConfig: layout, axes, indicators, precision, interaction, and overlay options.KlineChartColors: chart styling.KlineChartState: viewport and crosshair state for host synchronization.KlineChartDataState: list replacement, historical prepend, and timestamp-based realtime updates.KlineOverlayLine: generic price-level line and label.KlineHistoryMarker: above/below candle annotations.KlinePanelSpec: custom panel slot.KlineCustomIndicator: custom indicator calculation and drawing.KlineIndicator: reusable indicator formula abstraction for built-in and custom series.CandleRenderer: replaceable candle renderer.Use indicators for reusable formula-based indicators:
KlineChart(
dataState = dataState,
indicators = listOf(
klineIndicator(id = "MA120", pane = KlineIndicatorPane.Main, lookback = 120) { candles ->
listOf(KlineIndicatorLine("MA120", TechnicalIndicators.calculateMA(candles, 120) { it.close }))
},
klineIndicator(id = "MY_MACD_LINE", pane = KlineIndicatorPane.Sub, overlayId = "MACD") { candles ->
listOf(KlineIndicatorLine("X", candles.map { it.close }))
},
klineIndicator(id = "MY_PANEL", pane = KlineIndicatorPane.Sub, label = "MY") { candles ->
listOf(KlineIndicatorLine("C", candles.map { it.close }))
},
klineIndicator(
id = "BTC_MA20",
pane = KlineIndicatorPane.Main,
sourceCandles = btcCandles,
showLatestValue = true,
) { btc ->
listOf(KlineIndicatorLine("BTC MA20", TechnicalIndicators.calculateMA(btc, 20) { it.close }))
},
),
)pane = KlineIndicatorPane.Main: draw on the main chart.pane = KlineIndicatorPane.Sub with overlayId: draw on an existing sub-panel such as VOL, MACD, RSI, KDJ, WR, or OBV.pane = KlineIndicatorPane.Sub without overlayId: create a new sub-panel.sourceCandles: calculate the indicator from another candle stream and align it back to the chart candles by timestamp. It uses an independent hidden axis by default, so different price levels can be overlaid as trend lines. Use alignment = KlineIndicatorAlignment.Index for index-based alignment, or scaleMode = KlineIndicatorScaleMode.SharedPriceAxis when the values should share the main price axis.showLatestValue = true: show the indicator's latest visible value with the same dashed line and right-side label behavior as the latest price overlay.Implementation packages under io.github.icyoung.internal.* are not stable API.
From this directory:
./gradlew compileCommonMainKotlinMetadata
./gradlew desktopTestSample checks:
./gradlew -p sample :shared:compileCommonMainKotlinMetadata
./gradlew -p sample :androidApp:compileDebugKotlin
./gradlew -p sample :desktopApp:compileKotlin
./gradlew -p sample :shared:linkDebugFrameworkIosSimulatorArm64iOS sample:
xcodebuild -project sample/iosApp/iosApp.xcodeproj \
-scheme iosApp \
-configuration Debug \
-sdk iphonesimulator \
-destination 'generic/platform=iOS Simulator' \
build