我试图解决的表达式的形式(对应于下面称为“表达式”的变量)的关键点在所有情况下都是相同的,因为成功和失败之间唯一变化的是指数的值每个学期。
这是一个最小的可重现示例:
from sympy import symbols, Mul, diff, solve
from decimal import Decimal
class Histogram:
def __init__(self, bins, pdf):
self.bins = bins
self.pdf = pdf
histogram = Histogram(
bins=[-1, 0, 1],
pdf=[Decimal('0.454861111111111104943205418749130330979824066162109375'),
Decimal('0'),
Decimal('0.545138888888888839545643349993042647838592529296875')]
)
]
def computation(histogram):
A = Decimal('1')
e = Decimal('1')
M_factor = Decimal('1.0828567056280801')
x = symbols('x')
product_terms = []
profit = lambda cp: (e * M_factor ** cp - e) * x
commission = lambda cp: (e * M_factor ** cp + e) * Decimal('0.0005') * x
for candles_profit, freq in zip(histogram.bins, histogram.pdf):
profit_term = profit(candles_profit)
commission_term = commission(candles_profit)
term = ((A + profit_term - commission_term) / A) ** freq
product_terms.append(term)
expression = Mul(*product_terms)
derivative = diff(expression, x)
solutions = solve(derivative, x)
print("Solutions:", solutions)
computation(histogram)
上面计算函数中的“表达式”变量在调试器中变成以下内容:
(1.0 - 0.0774785191289289x)^0.454861111111111 \* (0.0818152772752661x + 1.0)^0.545138888888889
如果您使用上面的示例创建一个 python 文件并运行它,则在尝试查找表达式的关键点时它永远不会返回。
我看到的可以解释失败的独特功能是它的指数中有重复的小数,就像 2/3 这样的有理数。为了证实我的直觉,即这是错误的根源,我重新审视了形成该交易品种直方图的交易:131 笔位于 -1 桶中,157 笔位于 +1 桶中。 131/288 = 0.454861(重复 1),157/288 = 0.545138(重复 8)。因此,即使 Decimal 值在我们传递给计算函数的直方图中保留了许多精度位置,这些值也是不准确的因为重复会在一段时间后停止,但即使这样也没关系,因为 sympy 会在该点之前切断值。由于 sympy.solve 将我的输入 python 小数强制转换为 sympy 浮点数,而不是 sympy 有理数,因此可以合理地预期这是问题的根源吗?如果是,我该如何修改我的代码以允许计算正确解析而不是永远卡住?
使用 SymPy 时,浮点数是许多令人头痛的原因。尽可能使用准确的数字。如果您使用
nsimplify
将十进制数转换为有理数,将立即计算解决方案。
这几行代码:
expression = Mul(*product_terms)
# ...
print("Solutions:", solutions)
至:
expression = Mul(*product_terms).nsimplify()
# ...
print("Solutions:", solutions[0].n())