Skip to content

Instantly share code, notes, and snippets.

@ParfoisMeng
Last active April 28, 2021 02:05
Show Gist options
  • Save ParfoisMeng/3a845892795f15f358ce1d3ba820467c to your computer and use it in GitHub Desktop.
Save ParfoisMeng/3a845892795f15f358ce1d3ba820467c to your computer and use it in GitHub Desktop.
最佳配仓算法
import org.junit.Test
import java.math.BigDecimal
import kotlin.math.abs
class ExampleUnitTestKT {
@Test
fun main() {
val stocks = arrayListOf<StockConfig>(
StockConfig("白马", 20.94, 0.2),
StockConfig("韭菜", 3.13, 0.4),
StockConfig("杂毛", 6.2, 0.4),
)
stocks.forEach { println(it) }
println()
tradingScheme(50000.0, stocks)
}
private fun tradingScheme(totalMoney: Double, stocks: List<StockConfig>): List<StockConfig> {
println("初始资金配仓")
var money = totalMoney
var moneyOffset = money
var ratioOffset = 0.0
stocks.forEach {
it.expectedMoney = totalMoney * it.expectedRatio
it.actualRatio = it.actualMoney / totalMoney
it.realActualUnit = it.actualUnit
it.realActualMoney = it.actualMoney
it.realActualRatio = it.actualRatio
println("名称:${it.name}\t\t每手单价:${it.unitPrice}\t\t" +
"预期配比:${it.expectedRatio.format()}\t\t" +
"预期资金:${it.expectedMoney.format()}\t\t" +
"预期单位:${it.expectedUnit.format()}\t\t" +
"初步资金:${it.realActualMoney.format()}\t\t" +
"初步单位:${it.realActualUnit}\t\t" +
"初步配比:${it.realActualRatio.format()}\t\t" +
"最佳偏差:${it.moneyOffset.format()}\t\t")
money = totalMoney - it.realActualRatio
ratioOffset += abs(it.expectedRatio - it.realActualRatio)
moneyOffset -= it.realActualMoney
}
println("资金偏差:${moneyOffset.format()} " +
"配仓偏差:${ratioOffset.format()}")
println()
println("优化资金配仓")
var moneyOffsetTotal = 0.0
stocks.forEach { moneyOffsetTotal += it.moneyOffset }
var realMoneyOffset = totalMoney
var realRatioOffset = 0.0
stocks.forEach {
if (moneyOffsetTotal > 0) {
if (it.moneyOffset < 0) {
it.realActualUnit = it.actualUnit + 1
it.realActualMoney = it.realActualUnit * it.unitPrice
it.realActualRatio = it.realActualMoney / totalMoney
}
// } else {
// // 总余不足,需要其他股票降仓补足
// if (it.moneyOffset < 0 && abs(it.moneyOffset) < moneyOffset) {
// it.realActualUnit = it.actualUnit + 1
// it.realActualMoney = it.realActualUnit * it.unitPrice
// it.realActualRatio = it.realActualMoney / totalMoney
//
// moneyOffset -= abs(it.moneyOffset)
// }
}
println("名称:${it.name}\t\t每手单价:${it.unitPrice}\t\t" +
"预期配比:${it.expectedRatio.format()}\t\t" +
"预期资金:${it.expectedMoney.format()}\t\t" +
"预期单位:${it.expectedUnit.format()}\t\t" +
"真实资金:${it.realActualMoney.format()}\t\t" +
"真实单位:${it.realActualUnit}\t\t" +
"真实配比:${it.realActualRatio.format()}\t\t" +
"最少偏差:${it.realMoneyOffset.format()}\t\t")
realRatioOffset += abs(it.expectedRatio - it.realActualRatio)
realMoneyOffset -= it.realActualMoney
}
println("资金偏差:${realMoneyOffset.format()} " +
"配仓偏差:${realRatioOffset.format()}")
return stocks
}
data class StockConfig(
val name: String,
val price: Double,
val expectedRatio: Double,
) {
/**
* 单位价(每手单价)
*/
val unitPrice: Double = price * 100
// 预期配资
var expectedMoney: Double = 0.0
// 预期单位
val expectedUnit: Double get() = expectedMoney / unitPrice
// 初步的 实际配比 & 实际单位 & 实际配资 & 最佳偏差
val actualUnit: Int get() = expectedUnit.toInt()
val actualMoney: Double get() = actualUnit * unitPrice
var actualRatio: Double = 0.0
val moneyOffset: Double
get() {
val less = expectedMoney - actualMoney
val more = expectedMoney - (actualUnit + 1) * unitPrice
return if (less < abs(more)) less else more
}
// 真实的 实际配比 & 实际单位 & 实际配资 & 最少偏差
var realActualUnit: Int = actualUnit
var realActualMoney: Double = actualMoney
var realActualRatio: Double = actualRatio
val realMoneyOffset: Double get() = realActualMoney - expectedMoney
}
private fun Double.format(): Double = BigDecimal(this).setScale(2, BigDecimal.ROUND_HALF_UP).toDouble()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment