Skip to content

Instantly share code, notes, and snippets.

@kingjinho
Created December 14, 2021 12:56
Show Gist options
  • Save kingjinho/95b444fcd6081bb9850fd414066e1f43 to your computer and use it in GitHub Desktop.
Save kingjinho/95b444fcd6081bb9850fd414066e1f43 to your computer and use it in GitHub Desktop.
Find drawdowns

Thanks for reading my stackoverflow questions! Happy Early New 2022!!! :)))))))

class Drawdown {
    var peak: Quote? = null
    var trough: Quote? = null
    var recovered: Quote? = null
    var percentage: Double? = null
    var daysToRecover: String? = null
}

data class Quote(
    val price: Double,
    val date: String
)


class Drawdown {

    private fun findDrawdown(): List<Drawdown> {
        val list = mutableListOf<Drawdown>()
        var peak: Quote? = null
        var trough: Quote? = null
        var recovered: Quote? = null

        for (quotation in quotations) {
            val currentIdx = quotations.indexOf(quotation)
            if (currentIdx in 1 until quotations.size - 1) {
                val prevClosing = quotations[currentIdx - 1].price
                val nextClosing = quotations[currentIdx + 1].price
                val closing = quotation.price

                recovered = when {
                    peak == null -> null
                    closing >= peak.price -> {
                        if (peak.date != quotation.date) {
                            //can possibly be new peak
                            Quote(closing, quotation.date)
                        } else null
                    }
                    else -> null
                }

                peak = if (closing > prevClosing && closing > nextClosing) {
                    if ((peak == null || peak.price < closing) && recovered == null) {
                        Quote(closing, quotation.date)
                    } else peak
                } else peak

                trough = if (closing < prevClosing && closing < nextClosing) {
                    if (trough == null || trough.price > closing) {
                        Quote(closing, quotation.date)
                    } else trough
                } else trough


                if (recovered != null) {
                    val drawdown = Drawdown()
                    val percentage = (peak!!.price - trough!!.price) / peak.price

                    drawdown.peak = peak
                    drawdown.trough = trough
                    drawdown.recovered = recovered
                    drawdown.percentage = percentage
                    drawdown.daysToRecover =
                        ChronoUnit.DAYS.between(
                            LocalDate.of(
                                peak.date.substring(0, 4).toInt(),
                                peak.date.substring(4, 6).toInt(),
                                peak.date.substring(6, 8).toInt()
                            ),
                            LocalDate.of(
                                recovered.date.substring(0, 4).toInt(),
                                recovered.date.substring(4, 6).toInt(),
                                recovered.date.substring(6, 8).toInt()
                            ).plusDays(1)
                        ).toString()
                    list += drawdown
                    peak = if (closing > prevClosing && closing > nextClosing) {
                        Quote(recovered.price, recovered.date)
                    } else {
                        null
                    }
                    trough = null
                    recovered = null
                }
            }
        }
        val drawdown = Drawdown()
        val percentage = (peak!!.price - trough!!.price) / peak.price

        drawdown.peak = peak
        drawdown.trough = trough
        drawdown.recovered = recovered
        drawdown.percentage = percentage
        list += drawdown
        return list
    }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment