Last active
April 28, 2021 02:05
-
-
Save ParfoisMeng/3a845892795f15f358ce1d3ba820467c to your computer and use it in GitHub Desktop.
最佳配仓算法
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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