コード例 #1
0
    def __buildDriver__(self, driver_options):

        # Ubuntu
        if (os.name == 'posix'):
            chromedriver = 'chromedriver'

        # Windows
        if (os.name == 'nt'):
            chromedriver = 'chromedriver.exe'

        if chromedriver:

            if config.DRIVER_NAME == 'Chrome':
                logger.info("Using Chrome Driver ...")
                options = webdriver.ChromeOptions()
                options.add_experimental_option("excludeSwitches",
                                                ["enable-automation"])
                options.add_experimental_option('useAutomationExtension',
                                                False)
                options.add_experimental_option('w3c', False)

                for driver_option in driver_options:
                    # if "--proxy-server" in driver_option:
                    # 	print(f"\nADDING PROXY: [{driver_option}]\n")
                    options.add_argument(driver_option)

                capabilities = None
                if config.PROXY:
                    # print(f"\nADDING PROXY: [{config.PROXY}]\n")
                    # prox = Proxy()
                    # prox.proxy_type = ProxyType.MANUAL
                    # prox.http_proxy = config.PROXY
                    # # prox.socks_proxy = config.PROXY
                    # prox.ssl_proxy = config.PROXY

                    capabilities = webdriver.DesiredCapabilities.CHROME
                    capabilities['loggingPrefs'] = {'performance': 'ALL'}
                    # prox.add_to_capabilities(capabilities)

                if capabilities:
                    self.driver = webdriver.Chrome(
                        desired_capabilities=capabilities, options=options)
                    # self.driver = config.DRIVER_NAME(desired_capabilities=capabilities, options=options)
                else:
                    self.driver = webdriver.Chrome(chromedriver,
                                                   options=options)
                    # self.driver =  config.DRIVER_NAME(chromedriver, options=options)

            else:
                logger.info("Using Firefox Driver ...")
                self.driver = webdriver.Firefox()

        self.min_wait = WebDriverWait(self.driver, 5)
        self.max_wait = WebDriverWait(self.driver, 20)
        self.els_css = self.driver.find_elements_by_css_selector
        self.el_css = self.driver.find_element_by_css_selector
        self.els_xpath = self.driver.find_elements_by_xpath
        self.el_xpath = self.driver.find_element_by_xpath
        self.driver.set_script_timeout(30)
        return self.driver
コード例 #2
0
 def get_today_prices(self, time_slots_count=200):
     if time_slots_count < 0:
         raise ValueError("time_slots_count cannot be in negative")
     logging.info("getting today prices ...")
     r = requests.get(
         config.Todayprices_Url.format(time_slots_count,
                                       helpers.device_id()))
     return r.json()
コード例 #3
0
    def trade_insights(self,
                       Insights,
                       open_markets_only=True,
                       sort_by="growth"):

        if sort_by not in ("percentage", "growth"):
            raise Exception(
                f'<sort_by> value must be in {("percentage", "growth").join(" OR ")} '
            )
        logging.info(
            f"Getting Trade Insights of {'opened' if open_markets_only else 'all'} markets ..."
        )
        ClosingPrices = sorted(self.get_closing_prices(),
                               key=lambda k: float(k['InstrumentId']))
        Instruments = sorted(self.get_instruments(),
                             key=lambda k: float(k['InstrumentID']))
        InstrumentIds = [
            Instrument["InstrumentID"] for Instrument in Instruments
        ]

        res = []

        for elem in ClosingPrices:
            if elem['InstrumentId'] not in InstrumentIds:
                continue
            if open_markets_only and elem['IsMarketOpen'] == False:
                continue

            ElemInsight = helpers.find_in_list(Insights, 'instrumentId',
                                               elem['InstrumentId'])

            if not ElemInsight:
                continue

            InstrumentDetail = helpers.find_in_list(Instruments,
                                                    'InstrumentID',
                                                    elem['InstrumentId'])

            elem.update({
                k: v
                for k, v in InstrumentDetail.items() if k in (
                    "InstrumentDisplayName",
                    "SymbolFull",
                )
            })
            elem.update(ElemInsight)
            res.append(elem)

        res = sorted(res, key=lambda k: float(k[sort_by]), reverse=True)

        helpers.set_data(
            data=res,
            path=config.temp_dir +
            f"/{'opened' if open_markets_only else 'all'}_markets_insights_by_{sort_by}.json"
        )

        return res
コード例 #4
0
    def switch_account(self, to_demo=True):

        if to_demo and self.current_account_type == 'VIRTUAL':
            logger.info("Already on <VIRTUAL Account>")
            return True
        elif to_demo is False and self.current_account_type == 'REAL':
            logger.info("Already on <REAL Account>")
            return True

        if to_demo:
            self.close_popup()
            self.toggle_account_switcher

            if self.els_css('et-select-body-option'):
                self.els_css('et-select-body-option')[-1].click()
                self.els_css('.toggle-account-button')[0].click()

            logger.info("Switched to <VIRTUAL Account>")

        else:
            self.close_popup()
            self.toggle_account_switcher

            if self.els_css('et-select-body-option'):
                self.els_css('et-select-body-option')[0].click()
                self.els_css('.toggle-account-button')[0].click()

            logger.info("Switched to <REAL Account>")

        return True
コード例 #5
0
def get_etoro_instance():

    # Open Web Driver
    etoro_instance = Etoro()

    #Login To Site
    login_status = etoro_instance.login()

    if login_status is True:

        if config.AccountType == "VIRTUAL":
            logger.info(f"Switching to VIRTUAL Account ...")
            time.sleep(5)
            etoro_instance.switch_account(to_demo=True)
            time.sleep(3)

        if config.AccountType != etoro_instance.current_account_type:
            raise Exception(
                f"Switch Account Failed. should be <{config.AccountType}>"
                f" instead of <{etoro_instance.current_account_type}> !")

        return etoro_instance

    elif login_status is False and (etoro_instance.has_server_error
                                    or etoro_instance.site_not_reachable()):
        retries = 2
        while (login_status is False and retries < etoro_instance.MAX_RETRIES):
            logger.warning(
                f'Error Login :: {config.login_fail_msg}, Auto Retrying:'
                f'{retries}/{etoro_instance.MAX_RETRIES}')
            # del etoro_instance
            # etoro_instance = Etoro()
            etoro_instance.login()
            login_status = etoro_instance.get_loggedin_username()
            retries += 1

        if login_status is False:
            raise Exception("Max retries done to login but failed")

    else:
        raise Exception("Login Failed. Check Username or Password")
コード例 #6
0
    def login(self):
        try:

            self.openUrl(config.URL, title_display="<Etoro>")

            if self.already_loggedin:
                logger.info(f'Already Logged as User:"******".')
                return True

            logger.info(f'Attempting Login as User:"******".')
            driver_status = self.get_status_of_driver()

            if driver_status == "Dead":
                logger.error("Cannot Login ([Error:: '<Driver Not Alive>'")
                return False
            # logger.info('Driver getting url: {}'.format(config.URL))

            self.do_login_request()

            login_status = self.get_loggedin_username()

            if login_status:
                logger.info("Login Successful: '{}'".format(login_status))
                return True
            else:
                return False
        except Exception as e:
            logger.error("Cannot Login ([Error:: '<{}>'])".format(str(e)))
            return False
コード例 #7
0
    def do_login_request(self):
        if config.URL not in self.driver.current_url:
            self.openUrl(config.URL, title_display="Attempting Login <Etoro>")
        logger.info("Please wait Logging in ...")

        # self.wait_and_get_elems(config.user_elem)

        # self.wait_and_get_elems(config.password_elem)[0].send_keys(config.PASSWORD)
        # sleep(1)
        # self.wait_and_get_elems(config.submit_elem)[0].click()
        # sleep(2)

        # Login screen elements
        username_el = self.wait_and_get_elems(config.user_elem)

        if not username_el:
            if config.URL in self.driver.current_url:
                if self.has_server_error:
                    raise Exception(self.has_server_error)
                else:
                    raise Exception("Could not access site.")
            elif self.already_loggedin:
                return True
            else:
                raise Exception("Unknown error or access failed.")

        username_el = username_el[0]
        password_el = self.wait_and_get_elems(config.password_elem)[0]
        remember_me_el = self.wait_and_get_elems(config.remember_me_elem)[0]
        login_button_el = self.wait_and_get_elems(config.submit_elem)[0]

        # Perform the actions
        username_el.send_keys(config.USER)
        sleep(config.WAIT_BETWEEN_USER_ACTIONS)
        password_el.send_keys(config.PASSWORD)
        sleep(config.WAIT_BETWEEN_USER_ACTIONS)
        remember_me_el.click()
        sleep(config.WAIT_BETWEEN_USER_ACTIONS)
        login_button_el.click()
        sleep(config.WAIT_BETWEEN_USER_ACTIONS)
コード例 #8
0
def addLastOrderedTrade(openedTrade):
    """ add last ordered trades in json file"""
    trades = json_file_data(config.last_trade_done_file) or []

    #if openedTrade is selling trade =>
    #   find already exisiting trade for openedTrade in history and if buying found remove buying one
    if (openedTrade['IsBuy'] == False):
        openedTradeHistory = find_in_list(trades, "InstrumentID",
                                          openedTrade["InstrumentID"])
        if openedTradeHistory and openedTradeHistory["IsBuy"] == True:
            logging.info('Removing openedTrade buying trade history ...')
            trades.remove(openedTradeHistory)

    instrumentData = find_instrument_by_id(openedTrade['InstrumentID'])
    openedTrade.update({
        k: v
        for k, v in instrumentData.items()
        if k in ("InstrumentDisplayName", "SymbolFull")
    })
    trades.append(openedTrade)
    set_data(trades, config.last_trade_done_file)
    return json_file_data(config.last_trade_done_file)
コード例 #9
0
    def today_price_analysis(self,
                             stocks_sort_by,
                             time_slots_count=24,
                             open_markets_only=True,
                             time_slots_pick=2):

        logging.info(
            f"getting today's price analysis of {'opened' if open_markets_only else 'all'}"
            f" markets sorted by {stocks_sort_by} ...")

        file_name = f"markets_{'opened' if open_markets_only else 'all'}" \
           f"_{time_slots_count}_time_slots" \
           f"_time_compare_{time_slots_pick}_today_price_analysis.json"
        res = []

        for P in self.today_market_prices(time_slots_count=time_slots_count,
                                          open_markets_only=open_markets_only):
            PriceStats = {}
            InstrumentId = P['InstrumentId']
            Prices = P['Prices']

            if len(Prices) < time_slots_pick:
                # print(Prices, "\n")
                continue

            # d2 = parse(Prices[-1]['ToTime'])
            # d1 = parse(Prices[-3]['ToTime'])
            # print("dis -> ",(d2-d1).seconds/60)

            PricesToMonitor = Prices[int(f"-{time_slots_pick}"):]

            PricesRange = [_P['Price'] for _P in PricesToMonitor]

            PricesDateRange = [_P['ToTime'] for _P in PricesToMonitor]

            PricesRange = np.array(PricesRange, dtype=float)

            Dx = np.diff(PricesRange) / PricesRange[:-1] * 100

            # MaxIncrease = sum([100 * (b - a) / a for a, b in zip(PricesRange[::1], PricesRange[1::1])])/len(PricesRange)
            MaxIncrease = Dx.max() if Dx.any() else 0.00
            MeanIncrease = Dx.mean() if Dx.any() else 0.00
            PriceStats["InstrumentId"] = InstrumentId
            PriceStats["MaxIncrease"] = MaxIncrease
            PriceStats["MeanIncrease"] = MeanIncrease
            PriceStats["PricesRange"] = PricesToMonitor
            PriceStats["OfficialClosingPrice"] = P['OfficialClosingPrice']
            PriceStats["IsMarketOpen"] = P['IsMarketOpen']
            PriceStats["OfficialClosingPrice"] = P['OfficialClosingPrice']
            PriceStats["ClosingPrices"] = P['ClosingPrices']
            PriceStats["InstrumentDisplayName"] = P.get(
                'InstrumentDisplayName')
            PriceStats["ExchangeID"] = P.get('ExchangeID')
            PriceStats["SymbolFull"] = P.get('SymbolFull')
            res.append(PriceStats)

        res = sorted(res, key=lambda k: float(k[stocks_sort_by]), reverse=True)

        helpers.set_data(data=res, path=f"{config.temp_dir}/{file_name}")

        return res
コード例 #10
0
 def get_closing_prices(self):
     logging.info("getting closing prices ...")
     r = requests.get(config.Closingprices_Url + helpers.device_id())
     return r.json()
コード例 #11
0
 def get_instruments(self):
     logging.info("getting instruments data ...")
     return helpers.get_instruments(config.instruments_file)
コード例 #12
0
    def trade(self, ins, IsBuy=True):

        if helpers.is_digit(ins):
            InstrumentData = helpers.find_instrument_by_id(ins)
        else:
            InstrumentData = helpers.find_instrument_by_symbol(ins)

        if not InstrumentData:
            raise Exception(f"no Instrument found by: '{ins}'")

        Instrument = InstrumentData['SymbolFull']
        url = config.Market_Url.format(Instrument.lower().strip())
        res = ""

        if url not in self.driver.current_url:
            self.openUrl(
                url,
                title_display=f"Going to Trade <{Instrument}> IsBuy <{IsBuy}>")

        self.wait_and_get_elems('div[automation-id="trade-button"]')[0].click()

        if self.wait_and_get_elems(
                'a[href="https://www.etoro.com/trading/market-hours-and-events/"]'
        )[0].text == 'MARKET CLOSED':
            res = f"[MARKET CLOSED] Trade Cannot Be Opened for <{Instrument}> IsBuy:{IsBuy}"
            logger.warning(res)
            return False, res

        if IsBuy:
            self.wait_and_get_elems(
                'button[ng-class="{active: model.isBuy }"]')[0].click()
        else:
            #sell
            self.wait_and_get_elems(
                'button[ng-class="{active: !model.isBuy }"]')[0].click()

        #select leverage:
        self.wait_and_get_elems(
            'div[data-etoro-automation-id="execution-leverage-tab-title-value"]'
        )[0].click()
        leverages = self.wait_and_get_elems(
            'a[ng-repeat="leverage in model.displayLeverages"]')
        leverages[-1].click()  # select max leverage value

        if config.Trailing_Stop_Loss:
            self.el_css(
                "div[data-etoro-automation-id='execution-stop-loss-tab-title-label']"
            ).click()

            self.el_css(
                "input[data-etoro-automation-id='execution-stop-loss-editing-tsl-check-box']"
            ).click()

            if self.is_on_rate_view:
                #switch to amount view
                self.wait_and_get_elems(
                    "a[data-etoro-automation-id='execution-stop-loss-amount-editing-switch-to-rate-button']"
                )[0].click()

            stoploss_input = self.els_css(
                "input[data-etoro-automation-id='input']")[-1]
            stoploss_input.clear()

            amount_input = self.els_css(
                "input[data-etoro-automation-id='input']")[0]
            amount_input_val = float(
                amount_input.get_attribute("value").replace("$", "").replace(
                    ",", ""))

            if config.Max_Stop_Loss:
                stoploss_input.send_keys(
                    '999999' +
                    Keys.RETURN)  #this will validate and selects max SL
            else:
                stoploss_input.send_keys(
                    f'-{amount_input_val*float(config.Stop_Loss)}' +
                    Keys.RETURN)

        #click trade button
        self.wait_and_get_elems(
            'button[data-etoro-automation-id="execution-open-position-button"]'
        )[0].click()

        res = f"Trade Opened for <{Instrument}> IsBuy:{IsBuy} at {datetime.now()}"
        logger.info(res)

        #getting login info to check trade successfull ?
        openedTrade = helpers.isOrderOpened(InstrumentData["InstrumentID"],
                                            self.get_login_info, True)

        #save last trade done
        helpers.addLastOrderedTrade(openedTrade)

        return bool(openedTrade != {}), res
コード例 #13
0
def buy_trade(etoro_instance):
    try:
        detail = ""

        # etoro_instance.login()
        #checking  current balance
        clientCredit = helpers.clientCredit(
            login_data=etoro_instance.get_login_info)

        open_markets_only = config.analyze_open_markets_only
        logger.info(
            f"Analyzing Today Stocks For {'opened' if open_markets_only else 'all'} markets ..."
        )

        analyzer = AnalyzeStocks()

        top_markets = analyzer.today_price_analysis(
            stocks_sort_by=config.stocks_sort_by,
            time_slots_count=24,
            open_markets_only=open_markets_only,
            time_slots_pick=2)

        # top_markets = analyzer.trade_insights(
        # 	etoro_instance.get_insights(),
        #  	open_markets_only=open_markets_only, sort_by="growth")

        for t1, top_market in enumerate(top_markets):
            logger.info(f"\nGoing to open Buying Trade for :\n{top_market}\n")
            buy_trade, buy_trade_res = etoro_instance.trade(
                ins=top_market.get("InstrumentId"), IsBuy=True)
            if buy_trade is False:
                detail = (
                    f"Couldnot open buying position for: '{top_market.get('SymbolFull')}'"
                    f" reason :\n{buy_trade_res}\n")
                logger.warning(detail)
            else:
                detail = (
                    f"Opened buying position for: '{top_market.get('SymbolFull')}'"
                    f" response :\n{buy_trade_res}\n")
                logger.info(detail)
                break

        logger.info(f"\nGoing to update User Date ...")
        user_data = etoro_instance.get_login_info
        logger.info(f"\nGot User Data :\n{user_data}\n")

        logger.info(f"\nGoing to update User Trade History ...")
        user_trade_history = etoro_instance.get_trade_history
        logger.info(f"\nGot User Trade History :\n{user_trade_history}\n")

        msg = '<buy_trade> finished ...'
        print('+' * len(msg))
        print(msg)
        print('+' * len(msg))

    except Exception as e:
        exc_type, exc_obj, exc_tb = sys.exc_info()
        fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
        err_detail = e, fname, exc_tb.tb_lineno
        detail = f"Following Error occured in buy_trade ::\n{err_detail}\n"
        logger.error(detail)

    #write trade logs
    helpers.write_csv("Buying", detail)
コード例 #14
0
def sell_trade(etoro_instance):
    try:
        detail = ""
        # etoro_instance.login()

        logger.info(
            f"Going to get last Ordered Trades (For Opening Selling Position ) ..."
        )

        lastOrderedTrades = helpers.lastOrderedTrade(isBuy=True)

        if not lastOrderedTrades:
            logger.info(
                f"No Last Ordered Trades found to open a selling position.")

        for t1, lastOrderedTrade in enumerate(lastOrderedTrades):

            instrumentID = lastOrderedTrade['InstrumentID']
            instrumentData = helpers.find_instrument_by_id(instrumentID)
            lastOrderedTrade.update({
                k: v
                for k, v in instrumentData.items() if k in (
                    "InstrumentDisplayName",
                    "SymbolFull",
                )
            })
            instrumentSymbol = instrumentData["SymbolFull"]
            instrumentDisplayName = instrumentData["InstrumentDisplayName"]
            instrumentTitle = f"{instrumentSymbol} - {instrumentDisplayName}"
            positionID = lastOrderedTrade['PositionID']

            logger.info(
                f"\n[{t1+1}/{len(lastOrderedTrades)}] :\n{lastOrderedTrade}\n")

            logger.info(f"Going to get User Trade History ...")
            tradeHistory = etoro_instance.get_trade_history

            closedOrder = helpers.isOrderClosed(
                positionID,
                data_list=tradeHistory,
                path=config.closed_trade_history_file)

            if not closedOrder:
                logger.info(f"<[{instrumentTitle}]: postionID->"
                            f"{positionID} instrumentID->{instrumentID}>"
                            " is not closed yet. skipping this...")
                continue

            # here opens a selling postion for this trade

            logger.info(
                f"Going to open Selling Trade for: {instrumentTitle}\n")
            sell_trade, sell_trade_res = etoro_instance.trade(ins=instrumentID,
                                                              IsBuy=False)

            if sell_trade is False:
                detail = (
                    f"Couldnot open selling position for: '{instrumentTitle}'"
                    f" reason :\n{sell_trade_res}\n")
                logger.warning(detail)
            else:
                detail = (f"Opened selling position for: '{instrumentTitle}'"
                          f" response :\n{sell_trade_res}\n")
                logger.info(detail)

            logger.info(f"\nGoing to update User Date ...")
            user_data = etoro_instance.get_login_info
            logger.info(f"\nGot User Data :\n{user_data}\n")

            logger.info(f"\nGoing to update User Trade History ...")
            user_trade_history = etoro_instance.get_trade_history
            logger.info(f"\nGot User Trade History :\n{user_trade_history}\n")

        msg = "<sell_trade> finished ..."
        print('+' * len(msg))
        print(msg)
        print('+' * len(msg))

    except Exception as e:
        exc_type, exc_obj, exc_tb = sys.exc_info()
        fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
        err_detail = e, fname, exc_tb.tb_lineno
        detail = f"Following Error occured in sell_trade ::\n{err_detail}\n"
        logger.error(detail)

    #write trade logs
    helpers.write_csv("Selling", detail)
コード例 #15
0

if __name__ == '__main__':
    exchange_to_follow = helpers.get_exchange_info(config.Default_Exchange)
    day_of_week_opens = exchange_to_follow['Market Opens'].split()[0].lower(
    ).replace("day", "")
    day_of_week_closes = exchange_to_follow['Market Closes'].split()[0].lower(
    ).replace("day", "")
    exchange_closing = datetime.strptime(
        exchange_to_follow['Market Closes'].split()[1], "%H:%M")
    hour_minute = exchange_closing - timedelta(
        minutes=config.Exchange_Schedular_Minutes)
    day_of_week = f"{day_of_week_opens}-{day_of_week_closes}"

    logger.info(
        f"\nScheduler started at: {datetime.now().astimezone(pytz.timezone('UTC'))}\n"
    )
    logger.info(
        f"Trader For <{exchange_to_follow['Exchange']}> scheduled to run at:"
        f"\n[Day Weeks: {day_of_week}]\t[Exchange closing hour: "
        f"{exchange_closing.hour}:{exchange_closing.minute:02d} UTC]\t[Job starts at: "
        f"{hour_minute.hour}:{hour_minute.minute:02d} UTC]\n")

    #graps etoro instance with logged in driver and swticed to virtual/real account
    etoro_instance = get_etoro_instance()

    #scheduler = BlockingScheduler({'apscheduler.timezone': 'Europe/London'})
    scheduler = BlockingScheduler({'apscheduler.timezone': 'UTC'})

    # schedular to buy_trade
    scheduler.add_job(buy_trade,