64 lines
2.5 KiB
Ruby
64 lines
2.5 KiB
Ruby
class BetPlacementService < ApplicationJob
|
|
queue_as :high
|
|
|
|
def perform(args = {})
|
|
# do not proceed if we have already procssed a bet for this tip
|
|
bet = args[:bet]
|
|
# get a valid betfair instance for the account we are using, halt if not valid.
|
|
exchange = Integrations::Betfair::BetManager.new(bet.exchange_account)
|
|
return unless exchange
|
|
|
|
last_step = 'Checking event id'
|
|
begin
|
|
# check this bet with the exchange and populate the event id if it is missing
|
|
|
|
unless bet.exchange_event_id
|
|
bet.exchange_event_id = exchange.bet_event(bet)
|
|
end
|
|
bet.placement_attempts += 1
|
|
|
|
# check the odds are still good at the exchange for that event
|
|
last_step = 'Checking odds'
|
|
prices_and_stakes = exchange.bet_odds(bet)
|
|
prices = prices_and_stakes[:prices]
|
|
|
|
bet.exchange_odds = prices_and_stakes
|
|
bet.outcome = 'expired'
|
|
tip_odds = bet.tip_provider_odds.to_f
|
|
|
|
# use tip odds or get closest match to tip odds offered by the exchange
|
|
last_step = 'Determining if odds optimal'
|
|
margin = tip_odds * bet.exchange_account.current_stake_strategy[:odds_margin]
|
|
max_tip_odds = tip_odds + margin
|
|
odds_to_execute_at = prices.min_by { |num| (max_tip_odds - num).abs }
|
|
raise 'Cannot determine optimal odds' unless odds_to_execute_at
|
|
if odds_to_execute_at.between?(tip_odds, tip_odds + margin)
|
|
last_step = 'Determining stake and placing bet'
|
|
odds_stake = prices_and_stakes[:stakes][odds_to_execute_at.to_s]
|
|
|
|
bet.executed_odds = odds_to_execute_at.to_s
|
|
# stake will always fill the max available or the limits of our stake management - whichever is the lower.
|
|
stake = bet.exchange_account.optimal_stake(bet, exchange.minimum_stake, odds_stake)
|
|
|
|
raise 'Optimal stake is zero. Not taking bet' if stake.zero?
|
|
|
|
bet.outcome = 'open'
|
|
bet.stake = stake
|
|
bet.expected_value = Bet.calculate_expected_value(stake, odds_to_execute_at)
|
|
if bet.exchange_account.can_bet?
|
|
bet.exchange_bet_id = exchange.place_bet(bet, stake)
|
|
end
|
|
else
|
|
bet.log << '[Bet placement] Tip odds not found in latest prices, nudge too far out'
|
|
end
|
|
rescue Exception => e
|
|
x = "Placement #{bet.placement_attempts}--->Last step: #{last_step}. Error: #{e.message}. Skipping"
|
|
bet.log ||= []
|
|
bet.log << x
|
|
bet.outcome = e.message.include?('PERMISSION_DENIED') ? 'errored' : 'skipped'
|
|
ensure
|
|
bet.save!
|
|
end
|
|
end
|
|
end
|