bettermail/portal/app/jobs/bet_placement_service.rb
2022-11-12 02:27:46 +01:00

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