Esempio n. 1
0
 def order_logic(self, listing_list, bid_amt, filters_used):
     request = {"bid_requests": []}
     for l in listing_list:
         request['bid_requests'].append({
             "listing_id": l,
             "bid_amount": round(bid_amt, 2)
         })
         # TODO What happens if i get throttled!? Is Prosper API post / get throttled different or the same?? Monitor and modify if need error handling like in listing logic
     response = requests.post(
         default.config['prosper']['prosper_order_url'],
         json=request,
         headers=self.order_header).json()
     logging.log_it_info(self.logger,
                         "request = {request}".format(request=request))
     logging.log_it_info(self.logger,
                         "response = {response}".format(response=response))
     self.handle_order_sql(response, filters_used)
Esempio n. 2
0
    def listing_logic(self, query, query_get):
        already_invested_listings = self.connect.get_bid_listings(
        )  # Takes a fraction of a second, should be ok. Repetitive as submitted_order_listings will handle it, but perfer cutting the listing logic off if not needed
        listings_found = []
        throttled_count = 0
        track_filters = {}  # For tracking of what filters are finding notes
        i_got_throttled = True  # Sometimes get throttled, will run again if throttled
        while i_got_throttled:
            r = requests.get(query_get,
                             headers=self.listing_header,
                             timeout=30.0)
            query_listing = r.json()
            if 'result' in query_listing:  # Can get throttled so only execute if get a result
                # if 'result' may be slow
                result_length = len(query_listing['result'])
                if result_length > 0:
                    for i in range(result_length):
                        listing_number = query_listing['result'][i][
                            'listing_number']
                        prosper_rating = query_listing['result'][i][
                            'prosper_rating']
                        if listing_number not in already_invested_listings:
                            self.track_filter(
                                track_filters, listing_number, query,
                                prosper_rating
                            )  # populates track_filters dict to be inserted into psql later
                            if listing_number not in already_invested_listings:
                                listings_found.append(listing_number)
                                logging.log_it_info(
                                    self.logger,
                                    "filter {query} found listing: {listing} at {current_time}"
                                    .format(query=query,
                                            listing=listing_number,
                                            current_time=datetime.now()))

                i_got_throttled = False
            else:
                if 'errors' in query_listing:
                    # logging.log_it_info(self.logger, "query {query} got an error, error is: {error}".format(query=query, error=query_listing))
                    throttled_count += 1
                else:
                    logging.log_it_info(
                        self.logger,
                        "not an errors in response, response is: {response}".
                        format(response=query_listing))
        return listings_found, track_filters, throttled_count
Esempio n. 3
0
    def thread_worker(self, query, query_get, submitted_order_listings):
        logging.log_it_info(
            self.logger,
            "Started running {query} at {time}".format(query=query,
                                                       time=datetime.now()))
        listing_pings = 0
        order_pings = 0
        total_throttle_count = 0
        while time.time() < self.time_to_continuously_run_submit_orders:
            start_time = time.time()
            listings_found, filters_used, throttle_count = self.listing_logic(
                query=query, query_get=query_get)
            listing_pings += 1
            total_throttle_count += throttle_count
            if len(listings_found) > 0:
                with self.lock:
                    unique_listings = []
                    for listing in listings_found:
                        if listing not in submitted_order_listings:
                            submitted_order_listings.append(listing)
                            unique_listings.append(listing)
                    listings_to_invest, new_bid_amt, cash_used = self.handle_cash_balance(
                        self.remaining_cash, unique_listings)
                    self.remaining_cash -= cash_used  # Will count cash used towards an expired listing. Calculate cash on fly because get cash from prosper api not always quick enough
                if len(listings_to_invest) > 0:
                    logging.log_it_info(
                        self.logger,
                        "Listings to invest at {current_time}: {listings}".
                        format(listings=listings_to_invest,
                               current_time=datetime.now()))
                    self.order_logic(
                        listing_list=listings_to_invest,
                        bid_amt=new_bid_amt,
                        filters_used=filters_used
                    )  # Put in order, no need to sleep if order placed since that takes time
                    logging.log_it_info(
                        self.logger,
                        "Listings invested at {current_time}: {listings}".
                        format(current_time=datetime.now(),
                               listings=listings_to_invest))
                    # BUG Only inserting filters used if order placed... I prefer to have filters inserted if filter found something but overlaps with a previous filter will not insert... This was not a problem with run.py
                    order_pings += 1
                else:
                    self.wait_for_throttle_cap(start_time, self.min_run_time)
            else:
                self.wait_for_throttle_cap(start_time, self.min_run_time)

        self.connect.close_connection()
        logging.log_it_info(
            self.logger,
            "Ended running {query} at {time}, with {pings} pings to the listing api, and {order_ping} order pings to the order api, and ignored {throttle_count} throttles from api"
            .format(query=query,
                    time=datetime.now(),
                    pings=listing_pings,
                    order_ping=order_pings,
                    throttle_count=total_throttle_count))
Esempio n. 4
0
    def handle_cash_balance(self, available_cash, listings_list):
        investment_number = len(listings_list)
        if investment_number == 0:  # Handles no listings
            return listings_list, self.bid_amt, 0  # [], self.bid_amt, no cash used
        else:
            new_listing_list = listings_list
            new_amt = self.bid_amt
            aval_amt = available_cash / investment_number
            if available_cash >= 25:  # min bid for a listing
                if aval_amt < self.bid_amt:
                    if aval_amt <= available_cash:
                        if aval_amt >= 25:
                            situation_one_msg = "1: {cash} is not enough available cash for desired bid amount of {amt}, for {investment_number} listings, modifying to {new_amt}".format(
                                cash=available_cash,
                                investment_number=investment_number,
                                amt=self.bid_amt,
                                new_amt=aval_amt)
                            # self.amt = aval_amt
                            new_amt = aval_amt
                            logging.log_it_info(self.logger, situation_one_msg)
                        elif aval_amt <= 25 and investment_number > 1:
                            new_amt, new_listing_list = self.recalculate_bid_amount(
                                cash=available_cash,
                                listing_list=listings_list)
                            situation_two_msg = "2: {cash} is not enough available cash for desired bid amount of {amt}, for {investment_number}  listings, modifying to bids of {new_amt} for {listing_num} listings".format(
                                cash=available_cash,
                                investment_number=investment_number,
                                amt=self.bid_amt,
                                new_amt=new_amt,
                                listing_num=len(new_listing_list))
                            logging.log_it_info(self.logger, situation_two_msg)
                            # self.amt = new_bid_amt
                            # self.listings_list = new_listing_list

                else:
                    normal_op_msg = f"available_cash of {available_cash} is enough for normal bidding submission"
                    logging.log_it_info(self.logger, normal_op_msg)

            else:
                situation_three_msg = "Your available cash of {cash} is not enough to invest in anything... Wow dude".format(
                    cash=available_cash)
                logging.log_it_info(self.logger, situation_three_msg)
                new_listing_list = []
                # self.listings_list = []
            return new_listing_list, new_amt, len(
                new_listing_list) * new_amt  # May be the same as original
Esempio n. 5
0
 def handle_order_sql(self, response, filters_used_dict):
     # TODO error handling per error code type from prosper
     if "order_id" in response:
         try:
             sql = SQLMetrics()
             sql.run_listing_filters_used(
                 filters_used_dict
             )  # inserts the filters used into listings_filters_used for tracking
             sql.run_insert_bid_request(
                 response
             )  # TODO add error handling. Print the error and continue
             sql.run_insert_orders(response)
             sql.close_connection()
         except:  # TODO make specific for now catch all errors
             e = sys.exc_info()[0]
             logging.log_it_info(self.logger, e)
     if 'code' in response:  # Sometimes a listing_id cannot be invested in
         # Example response {'code': 'ORD0019', 'message': 'Listing [10846973] is in status [PENDING_COMPLETION] and cannot currently accept bids.'}
         try:
             listing_string = response['message']
             end_index = listing_string.find("]")
             pending_completion_listing = listing_string[9:end_index]
             sql = SQLMetrics()
             sql.run_insert_bid_request_pending_completion(
                 pending_completion_listing
             )  # This adds the listing to bid_requests table and therefore will be excluded in the future runs
             logging.log_it_info(
                 self.logger,
                 "Added {listing} to pending_completion_listings list".
                 format(listing=pending_completion_listing))
             sql.close_connection()
         except TypeError as type_error:
             logging.log_it_info(
                 self.logger,
                 "type error: {error}".format(error=type_error))
         except:
             e = sys.exc_info()[0]
             logging.log_it_info(self.logger, e)