Reputation: 180512
I am using the following python code in a Kivy application. The code works fine and displays the correct information but is quite slow when calculating the return values and displaying to the screen. My questions are:
could I write the function in C and use cython to incorporate it to my python program.
if I can, would there be any noticeable speed increase or does the problem lie somewhere else?
def offset_back(initial_bet, initial_odds):
returns = []
new_odds = Decimal(initial_odds)
while new_odds > 1:
# calculate tick based on size of odds
if 50 < new_odds <= 100:
tick = Decimal("5.0")
elif 30 < new_odds <= 50:
tick = Decimal("2.0")
elif 20 < new_odds <= 30:
tick = Decimal("1.0")
elif 10 < new_odds <= 20:
tick = Decimal("0.5")
elif 6 < new_odds <= 10:
tick = Decimal("0.2")
elif 4 < new_odds <= 6:
tick = Decimal("0.1")
elif 3 < new_odds <= 4:
tick = Decimal(".05")
elif 2 < new_odds <= 3:
tick = Decimal(".02")
elif new_odds <= 2:
tick = Decimal(".01")
else:
tick = Decimal("10")
# calculate percentage difference between initial bet and new odds
drop = Decimal(100 - (100 * Decimal(initial_odds) / Decimal(new_odds))) / 100
# calculate amount needed to increase bet by to cancel liability
increase = abs((initial_bet * drop))
# calculate new stake
new_bet = (initial_bet + increase)
# calculate potential profit based on the new stake - initial invested stake
profit = (new_bet - initial_bet)
returns.append(" Stake: %.2f" % abs(new_bet)+ " " * spacing + "Odds: " "%.2f" % abs(new_odds)+ " " * spacing + "Profit: " "%.2f" % abs(profit))
new_odds -= tick
return returns
Upvotes: 0
Views: 700
Reputation: 13610
First suggestion:
Here are some suggestions, try to move the Decimal declarations out of the loop, just reference to them when adding/substracting. As long as you created them once, it should be much faster.
decimals = [
Decimal("10")
,Decimal("5.0")
,Decimal("2.0")
,Decimal("1.0")
,Decimal("0.5")
,Decimal("0.2")
,Decimal("0.1")
,Decimal(".05")
,Decimal(".02")
,Decimal(".01")
]
And replace the if by something like this:
if 50 < new_odds <= 100:
tick = decimals[1]
Second suggestion:
is to remove the if else if ...
, as you don't always get into the first if, you have to do at worse a lot of comparison to get the right case. Replace the if block for something like this.
thick = decimals[getThick(new_odds)]
The getThick
should implement a formula that can be transformed to indexes. I guess your thick function could be expressed mathematically.
Here using bisect_left
as Hugh proposed would be a good idea unless you can come up with a function that does that by calculation.
Third suggestion:
Replace that line by a format string:
returns.append(" Stake: %.2f %s Odds: %.2f %s Profit: %.2f" %
(abs(new_bet), spacing, abs(new_odds), spacing, abs(profit)))
Upvotes: 2
Reputation: 56694
Avoid using Decimal - nothing you are doing here requires absolute precision.
Convert the if..then cascade to a binary lookup with bisect
I don't understand exactly what some of your math accomplishes, but I am very leery of your use of abs()
here. Are you sure that's what you want?
May not be a good idea, but for sake of demonstration: I have converted the function to a generator function using the yield
statement; instead of returning an array of strings, it returns a string at a time.
.
from bisect import bisect_left
breakpoints = [-1., 2., 3., 4., 6., 10., 20., 30., 50., 100.]
ticks = [0., 0.01, 0.02, 0.05, 0.1, 0.2, 0.5, 1., 2., 5., 10.]
def offset_back(initial_bet, initial_odds, breakpoints=breakpoints, ticks=ticks):
new_odds = initial_odds
while new_odds > 1.:
# calculate tick based on size of odds
tick = ticks[bisect_left(breakpoints, new_odds)]
# calculate percentage difference between initial bet and new odds
drop = 1. - initial_odds / new_odds
# calculate new stake, increased to cancel liability
new_bet = initial_bet + abs(initial_bet * drop) # are you sure abs() is correct here?
# calculate potential profit based on the new stake - initial invested stake
profit = new_bet - initial_bet
new_odds -= tick
yield " Stake: {stake:0.2f} Odds: {odds:0.2f} Profit: {profit:0.2f}".format(stake=abs(new_bet), odds=abs(new_odds), profit=abs(profit))
Upvotes: 2