Esempio n. 1
0
 def __init__(self) -> None:
     super().__init__()
     self.__alpaca_client: AlpacaClient = AlpacaClient()
     self.__iex_cloud_client: IexCloudClient = IexCloudClient()
     self.__td_ameritrade_client: TdAmeritradeClient = TdAmeritradeClient()
     self.__email_client: EmailClient = EmailClient()
     self.__stock_service: StockService = StockService()
     self.__calc_service: CalcService = CalcService()
Esempio n. 2
0
 def test_max_profit_period(self):
     data_rows = [['A', '01-Jan-2012', '100'], ['A', '02-Jan-2012', '95'],
                  ['A', '04-Jan-2012', '100'], ['A', '03-Jan-2012', '96'],
                  ['A', '08-Jan-2012', '8'], ['A', '05-Jan-2012', '0'],
                  ['A', '06-Jan-2012', '3'], ['A', '07-Jan-2012', '5']]
     s = StockService(data_rows)
     stock_search = StockSearchFilter('A',
                                      datetime.fromisoformat('2012-01-02'),
                                      datetime.fromisoformat('2012-02-01'))
     buy_stock, sell_stock, profit = s.get_max_profit_period(stock_search)
     self.assertEquals(
         buy_stock, StockInfo('a', datetime.fromisoformat('2012-01-05'),
                              0.0))
     self.assertEquals(
         sell_stock,
         StockInfo('a', datetime.fromisoformat('2012-01-08'), 8.0))
     self.assertEqual(profit, 8)
Esempio n. 3
0
def handle_transaction(
    stocks_service: StockService
) -> Tuple[float, Optional[float], datetime.date, datetime.date, float]:
    stock_search_filter = input_helper.get_stock_search_filter(
        stocks_service.get_unique_stock_names())
    stocks = stocks_service.get_stocks(stock_search_filter)
    stock_prices = [i.price for i in stocks]

    m = None
    s = None
    if len(stock_prices) >= 1:
        m = mean([i.price for i in stocks])
    if len(stock_prices) >= 2:
        s = stdev([i.price for i in stocks])

    buying_stock_info, sell_stock_info, profit_made = stocks_service.get_max_profit_period(
        stock_search_filter)

    return (m, s,
            buying_stock_info.date if buying_stock_info is not None else None,
            sell_stock_info.date if sell_stock_info is not None else None,
            profit_made * 100)
Esempio n. 4
0
def init(file_name: str) -> StockService:
    try:
        csv_util = CSVFile(file_name, True)
        csv_util.read_file()
    except FileNotFoundError:
        print("Please pass a fully qualified path name to the CSV file")
        sys.exit(2)

    header = csv_util.get_header()
    if header != ["StockName", "StockData", "StockPrice"]:
        print(
            'Please provide a valid Stock Input File with "StockName", "StockData" and "StockPrice" as headers'
        )
        sys.exit(2)

    data_rows = csv_util.get_data_rows()
    stocks_service = StockService(data_rows)
    return stocks_service
Esempio n. 5
0
 def __init__(self, *args, **kwargs):
     super(TestIexCloudClient, self).__init__(*args, **kwargs)
     self.__iex_cloud_client: IexCloudClient = IexCloudClient()
     self.__stock_service: StockService = StockService()
Esempio n. 6
0
 def __init__(self) -> None:
   super().__init__()
   self.__alpaca_client: AlpacaClient = AlpacaClient()
   self.__iex_cloud_client: IexCloudClient = IexCloudClient()
   self.__email_client: EmailClient = EmailClient()
   self.__stock_service: StockService = StockService()
Esempio n. 7
0
 def __init__(self) -> None:
     super().__init__()
     self.__stock_service = StockService()
     self.__calc_service = CalcService()
Esempio n. 8
0
class BackTestService(BaseService):
    def __init__(self) -> None:
        super().__init__()
        self.__stock_service = StockService()
        self.__calc_service = CalcService()

    def run(self, req: BackTestRunRequest) -> BackTestRunResponse:
        if not req or not req.is_valid_model():
            raise BadRequestException()
        response: BackTestRunResponse = BackTestRunResponse(req)

        # Init Symbols
        symbols: List[SymbolMaster] = self.__get_symbols__(req)

        # Init Prices
        prices: DataFrame = self.__get_prices__(req, symbols)

        # Do Base Preparation
        prices[AppConsts.CUSTOM_COL_PV] = prices[
            AppConsts.PRICE_COL_CLOSE] * prices[AppConsts.PRICE_COL_VOLUME]
        for s in symbols:
            prices = self.__calc_service.append_sma(
                prices=prices,
                index=[s.id],
                sma_period=AppConsts.ADV_PERIOD_DFLT,
                sma_column_name=AppConsts.CUSTOM_COL_ADV,
                target_column=AppConsts.PRICE_COL_VOLUME)
            prices = self.__calc_service.append_sma(
                prices=prices,
                index=[s.id],
                sma_period=AppConsts.ADPV_PERIOD_DFLT,
                sma_column_name=AppConsts.CUSTOM_COL_ADPV,
                target_column=AppConsts.CUSTOM_COL_PV)

        LogUtils.debug('Prices shape after base preparation={0}'.format(
            prices.shape))

        # region Init Service
        strategy_service: Any = self.__stock_service.get_strategy_service(
            req.strategy_type, req.strategy_request, symbols, prices)
        if not strategy_service or not strategy_service._is_valid_request():
            raise BadRequestException()
        strategy_service._do_preparations()

        LogUtils.debug('Prices shape after strategy preparation={0}'.format(
            prices.shape))
        # endregion

        LogUtils.debug(prices.info())

        # region Init Dates
        start_date: date = DateUtils.add_business_days(req.date_from_obj, -1)
        start_date = DateUtils.add_business_days(start_date, 1)
        start_date_str: str = DateUtils.to_string(start_date)
        end_date: date = DateUtils.add_business_days(req.date_to_obj, -1)
        dates: DataFrame = self.__stock_service.get_dates(
            prices, start_date, end_date)

        LogUtils.debug(
            'Dates actual_start={0}, actual_end={1}, shape={2}'.format(
                start_date, end_date, dates.shape))
        # endregion

        # region Loop Dates
        strategy_item: BackTestResultItem = next(
            b for b in response.back_test_result_items
            if b.target == req.strategy_type)
        strategy_item.capital[start_date_str] = req.start_capital
        strategy_item.capital_available[start_date_str] = req.start_capital
        portfolio: Dict = {}

        for i, date_row in dates.iterrows():
            current_date = date_row[AppConsts.PRICE_COL_DATE]
            current_date_str: str = DateUtils.to_string(current_date)
            next_date = date_row[AppConsts.CUSTOM_COL_NEXT_DATE]
            next_date_str = DateUtils.to_string(next_date)
            next_next_date = date_row[AppConsts.CUSTOM_COL_NEXT_NEXT_DATE]

            shuffle(symbols)
            for symbol in symbols:
                has_price: bool = (symbol.id, current_date) in prices.index
                if not has_price:
                    continue
                price: Series = prices.loc[symbol.id, current_date]

                if symbol.instrument == AppConsts.INSTRUMENT_ETF:

                    # region Benchmark
                    b_result_item: BackTestResultItem = next(
                        b for b in response.back_test_result_items
                        if b.target == symbol.symbol)
                    if not b_result_item:
                        continue

                    if not b_result_item.transactions:
                        no_of_shares: int = self.__stock_service.get_no_of_shares(
                            req.start_capital, req.pct_risk_per_trade,
                            req.volume_limit, price, req.slippage)
                        if no_of_shares == 0:
                            LogUtils.warning('0 shares for ETF={0}'.format(
                                symbol.symbol))
                            continue

                        b_transaction: Transaction = Transaction()
                        b_transaction.symbol_master = symbol
                        b_transaction.action = AppConsts.ACTION_BUY
                        b_transaction.start_date = current_date
                        b_transaction.start_price = price.loc[
                            AppConsts.PRICE_COL_OPEN]
                        b_transaction.no_of_shares = no_of_shares
                        b_result_item.transactions.append(b_transaction)
                        b_result_item.capital[
                            current_date_str] = req.start_capital
                    else:
                        b_transaction: Transaction = b_result_item.transactions[
                            0]
                        b_transaction.end_date = current_date
                        b_transaction.end_price = price.loc[
                            AppConsts.PRICE_COL_CLOSE]
                        b_transaction.set_readonly_props()
                        b_result_item.capital[
                            current_date_str] = self.__calc_benchmark_capital(
                                req, b_transaction.start_price,
                                b_transaction.end_price,
                                b_transaction.no_of_shares)
                    b_result_item.ttl_no_days += 1
                    # endregion

                else:

                    # region Strategy
                    strategy_service._do_calculations(symbol.id, current_date)
                    action: str = strategy_service._get_action()

                    is_in_position: bool = symbol.id in portfolio
                    if not is_in_position:

                        if len(portfolio
                               ) == req.portfolio_max:  # todo: prioritize?
                            continue
                        if current_date == end_date or next_date >= end_date:
                            continue
                        has_next_price: bool = (symbol.id,
                                                next_date) in prices.index
                        has_next_next_price: bool = (
                            symbol.id, next_next_date) in prices.index
                        if not has_next_price or not has_next_next_price:
                            continue
                        adv: float = price.loc[
                            AppConsts.CUSTOM_COL_ADV] if price.loc[
                                AppConsts.CUSTOM_COL_ADV] > 0 else price.loc[
                                    AppConsts.PRICE_COL_VOLUME]
                        if adv < req.adv_min:
                            continue
                        adpv: float = price.loc[
                            AppConsts.CUSTOM_COL_ADPV] if price.loc[
                                AppConsts.CUSTOM_COL_ADPV] > 0 else price.loc[
                                    AppConsts.CUSTOM_COL_PV]
                        if adpv < req.adpv_min:
                            continue

                        next_price: Series = prices.loc[symbol.id, next_date]

                        has_entry_conditions: bool = strategy_service._has_entry_conditions(
                            symbol.id, current_date)
                        if has_entry_conditions:

                            no_of_shares: int = self.__stock_service.get_no_of_shares(
                                strategy_item.
                                capital_available[current_date_str],
                                req.pct_risk_per_trade, req.volume_limit,
                                next_price, req.slippage,
                                action == AppConsts.ACTION_BUY)
                            if no_of_shares == 0:
                                continue

                            trans: Transaction = Transaction()
                            trans.symbol_master = symbol
                            trans.action = action
                            trans.start_date = next_date
                            trans.start_price = next_price.loc[
                                AppConsts.PRICE_COL_OPEN]
                            trans.no_of_shares = no_of_shares

                            trans_amount: float = NumberUtils.round(
                                trans.start_price * no_of_shares)
                            strategy_item.capital_available[
                                current_date_str] -= trans_amount

                            # Add to portfolio
                            portfolio[symbol.id] = trans

                    elif is_in_position:

                        has_exit_conditions: bool = strategy_service._has_exit_conditions(
                            symbol.id, current_date)
                        has_next_next_price: bool = (
                            symbol.id, next_next_date) in prices.index
                        if next_date == end_date or not has_next_next_price or has_exit_conditions:

                            next_price: Series = prices.loc[symbol.id,
                                                            next_date]
                            next_open_price: float = next_price.loc[
                                AppConsts.PRICE_COL_OPEN]
                            slippage_price: float = 0
                            if action == AppConsts.ACTION_BUY:
                                slippage_price: float = NumberUtils.round(
                                    next_open_price -
                                    (next_open_price * AppConsts.BASIS_POINT *
                                     req.slippage))
                            else:
                                slippage_price: float = NumberUtils.round(
                                    next_open_price +
                                    (next_open_price * AppConsts.BASIS_POINT *
                                     req.slippage))
                            trans: Transaction = portfolio.get(symbol.id)
                            trans.end_date = next_date
                            trans.end_price = slippage_price
                            trans.set_readonly_props()
                            strategy_item.transactions.append(trans)

                            if action == AppConsts.ACTION_BUY:
                                trans_amount = NumberUtils.round(
                                    trans.end_price * trans.no_of_shares)
                                strategy_item.capital_available[
                                    current_date_str] += trans_amount
                            else:
                                init_trans_amount = NumberUtils.round(
                                    trans.start_price * trans.no_of_shares)
                                strategy_item.capital_available[
                                    current_date_str] += init_trans_amount
                                strategy_item.capital_available[
                                    current_date_str] += trans.change_in_capital

                            # Remove from portfolio
                            portfolio.pop(symbol.id, None)

                    # endregion

            # capital = capital available + capital in portfolio
            capital: float = strategy_item.capital_available[current_date_str]
            for key, val in portfolio.items():
                price: Series = prices.loc[key, current_date]
                capital += price.loc[
                    AppConsts.PRICE_COL_CLOSE] * val.no_of_shares
            strategy_item.capital[current_date_str] = NumberUtils.round(
                capital)
            strategy_item.ttl_no_days += 1
            strategy_item.capital[next_date_str] = strategy_item.capital[
                current_date_str]
            strategy_item.capital_available[
                next_date_str] = strategy_item.capital_available[
                    current_date_str]

        # endregion

        for result_item in response.back_test_result_items:
            result_item.set_readonly_props()
        return response

    def __get_symbols__(self, req: BackTestRunRequest) -> List[SymbolMaster]:
        if not req or req.test_limit_symbol <= 0:
            raise BadRequestException()
        symbols: List[SymbolMaster] = self.__stock_service.get_symbols(
            AppConsts.INSTRUMENT_STOCK,
            [AppConsts.SYMBOL_STATUS_EXCLUDE_TRADE])
        if not symbols:
            raise DbConnectionException()
        shuffle(symbols)
        symbols = symbols[:req.test_limit_symbol]
        if req.benchmark_etfs:
            for benchmark_etf in req.benchmark_etfs:
                etf_symbol: SymbolMaster = self.__stock_service.get_symbol(
                    benchmark_etf, AppConsts.INSTRUMENT_ETF)
                if not etf_symbol:
                    continue
                symbols.append(etf_symbol)
        LogUtils.debug('Symbol Count={0}'.format(len(symbols)))
        return symbols

    def __get_prices__(self, req: BackTestRunRequest,
                       symbols: List[SymbolMaster]) -> DataFrame:
        if not req or not symbols:
            raise BadRequestException()

        price_items: List[Any] = []
        for symbol in symbols:
            temp: List[Any] = []
            if symbol.instrument == AppConsts.INSTRUMENT_STOCK:
                temp = self.__stock_service.get_stock_prices_daily(
                    symbol.id, req.date_from_obj, req.date_to_obj)
            elif symbol.instrument == AppConsts.INSTRUMENT_ETF:
                temp = self.__stock_service.get_etf_prices_daily(
                    symbol.id, req.date_from_obj, req.date_to_obj)
            if temp:
                price_items.extend(temp)

        prices: DataFrame = self.__stock_service.get_price_dataframe(
            price_items)

        LogUtils.debug('Prices Init Shape={0}'.format(prices.shape))
        return prices

    def __calc_benchmark_capital(self, req: BackTestRunRequest,
                                 start_price: float, end_price: float,
                                 no_of_shares: int) -> float:
        capital: float = req.start_capital - (start_price * no_of_shares)
        return NumberUtils.round(capital + (end_price * no_of_shares))
Esempio n. 9
0
 def __init__(self, *args, **kwargs):
     super(TestImportService, self).__init__(*args, **kwargs)
     self.__import_service: ImportService = ImportService()
     self.__stock_service: StockService = StockService()
Esempio n. 10
0
class ImportCsvService(BaseService):
    def __init__(self) -> None:
        super().__init__()
        self.__stock_service = StockService()

# region KIBOT

    def import_from_csv_symbols(self) -> str:
        files: List[str] = FileUtils.get_files(AppConsts.STOCK_PRICE_FOLDER)
        for file in files:
            symbol: str = FileUtils.get_wo_ext(file)
            org_symbol: SM = self.__stock_service.get_symbol(
                symbol, AppConsts.INSTRUMENT_STOCK)
            if org_symbol:
                continue
            LogUtils.debug('Inserting {0}.'.format(symbol))
            BaseService._insert(
                SM(symbol=symbol,
                   name='',
                   status=AppConsts.SYMBOL_STATUS_INIT,
                   instrument=AppConsts.INSTRUMENT_STOCK))
        return "1"

    def import_from_csv_prices(self) -> str:
        BaseService._truncate(SPD)

        files: List[str] = FileUtils.get_files(AppConsts.STOCK_PRICE_FOLDER,
                                               is_full=True)
        for file in files:
            symbol: str = FileUtils.get_wo_ext(FileUtils.get_base_name(file))
            org_symbol: SM = self.__stock_service.get_symbol(
                symbol, AppConsts.INSTRUMENT_STOCK)
            if not org_symbol:
                continue
            records: List[List[str]] = CsvUtils.parse_as_list(file)
            if not records:
                continue
            for record in records:
                record[AppConsts.KIBOT_IDX_DATE] = DateUtils.get_date(
                    record[AppConsts.KIBOT_IDX_DATE],
                    AppConsts.KIBOT_DATE_FORMAT)
                record.insert(0, org_symbol.id)
            BaseService._insert_bulk(SPD, records)
        return "1"

# endregion

# region INTRINIO

    def import_from_csv_companynames(self) -> str:
        file: str = FileUtils.get_file(AppConsts.INCOME_STMT_FILE)
        records: List[Dict] = CsvUtils.parse_as_dict(file)
        curr_symbol: str = ''
        for record in records:
            symbol: str = record.get(AppConsts.INTRINIO_KEY_INC_STMT_TICKER)
            company_name: str = record.get(
                AppConsts.INTRINIO_KEY_INC_STMT_NAME)
            if symbol == curr_symbol or StringUtils.isNullOrWhitespace(
                    company_name):
                continue
            curr_symbol = symbol
            org_symbol: SM = self.__stock_service.get_symbol(
                curr_symbol, AppConsts.INSTRUMENT_STOCK)
            if not org_symbol:
                continue
            LogUtils.debug('Updating {0}.'.format(company_name))
            org_symbol.name = company_name
            BaseService._update()
        return "1"

    def import_from_csv_incomestatements(self) -> str:
        BaseService._truncate(FN)

        file: str = FileUtils.get_file(AppConsts.INCOME_STMT_FILE)
        records: List[Dict] = CsvUtils.parse_as_dict(file)
        models: List[Any] = []
        for record in records:
            if not self.__is_valid_intrinio_record(record):
                continue
            symbol: str = record.get(AppConsts.INTRINIO_KEY_INC_STMT_TICKER)
            fiscal_period: str = record.get(
                AppConsts.INTRINIO_KEY_INC_STMT_FISC_PD)
            org_symbol: SM = self.__stock_service.get_symbol(
                symbol, AppConsts.INSTRUMENT_STOCK)
            if not org_symbol:
                continue
            quarter_end_dte: date = DateUtils.get_date(
                record.get(AppConsts.INTRINIO_KEY_INC_STMT_END_DTE),
                AppConsts.INTRINIO_END_DTE_FMT)
            file_date: date = DateUtils.get_date(
                record.get(AppConsts.INTRINIO_KEY_INC_STMT_FILE_DTE),
                AppConsts.INTRINIO_FILE_DTE_FMT)
            models.append(
                (org_symbol.id,
                 record.get(AppConsts.INTRINIO_KEY_INC_STMT_FISC_YR),
                 self.__get_quarter(fiscal_period), quarter_end_dte, file_date,
                 None,
                 NumberUtils.to_float(
                     record.get(AppConsts.INTRINIO_KEY_INC_STMT_TTLREV)),
                 NumberUtils.to_float(
                     record.get(AppConsts.INTRINIO_KEY_INC_STMT_TTLPROF)),
                 NumberUtils.to_float(
                     record.get(AppConsts.INTRINIO_KEY_INC_STMT_TTLOPINC)),
                 NumberUtils.to_float(
                     record.get(AppConsts.INTRINIO_KEY_INC_STMT_NETINC)), None,
                 None, None, None, None, None, None, None, None, None, None,
                 None, None, None, None, None, None, None, None))
        BaseService._insert_bulk(FN, models)
        return "1"

    def import_from_csv_balancesheets(self) -> str:
        file: str = FileUtils.get_file(AppConsts.BALANCE_SHEET_FILE)
        records: List[Dict] = CsvUtils.parse_as_dict(file)
        for record in records:
            if not self.__is_valid_intrinio_record(record):
                continue
            symbol: str = record.get(AppConsts.INTRINIO_KEY_BLNC_SHEET_TICKER)
            fiscal_period: str = record.get(
                AppConsts.INTRINIO_KEY_BLNC_SHEET_FISC_PD)
            year: int = NumberUtils.to_int(
                record.get(AppConsts.INTRINIO_KEY_BLNC_SHEET_FISC_YR))
            quarter: int = self.__get_quarter(fiscal_period)
            org_symbol: SM = self.__stock_service.get_symbol(
                symbol, AppConsts.INSTRUMENT_STOCK)
            if not org_symbol:
                continue
            org_fn: FN = self.__stock_service.get_financial(
                org_symbol.id, year, quarter)
            if not org_fn:
                continue
            org_fn.current_assets = NumberUtils.to_float(
                record.get(AppConsts.INTRINIO_KEY_BLNC_SHEET_CURR_ASSETS))
            org_fn.ttl_assets = NumberUtils.to_float(
                record.get(AppConsts.INTRINIO_KEY_BLNC_SHEET_ASSETS))
            org_fn.current_liabilities = NumberUtils.to_float(
                record.get(AppConsts.INTRINIO_KEY_BLNC_SHEET_CURR_LIABS))
            org_fn.ttl_liabilities = NumberUtils.to_float(
                record.get(AppConsts.INTRINIO_KEY_BLNC_SHEET_LIABS))
            org_fn.ttl_equity = NumberUtils.to_float(
                record.get(AppConsts.INTRINIO_KEY_BLNC_SHEET_EQUITY))
            BaseService._update()
        return "1"

    def import_from_csv_calculations(self) -> str:
        file: str = FileUtils.get_file(AppConsts.FINANCIAL_CALCS_FILE)
        records: List[Dict] = CsvUtils.parse_as_dict(file)
        for record in records:
            if not self.__is_valid_intrinio_record(record):
                continue
            symbol: str = record.get(AppConsts.INTRINIO_KEY_CALCS_TICKER)
            fiscal_period: str = record.get(
                AppConsts.INTRINIO_KEY_CALCS_FISC_PD)
            year: int = NumberUtils.to_int(
                record.get(AppConsts.INTRINIO_KEY_CALCS_FISC_YR))
            quarter: int = self.__get_quarter(fiscal_period)
            org_symbol: SM = self.__stock_service.get_symbol(
                symbol, AppConsts.INSTRUMENT_STOCK)
            if not org_symbol:
                continue
            org_fn: FN = self.__stock_service.get_financial(
                org_symbol.id, year, quarter)
            if not org_fn:
                continue
            org_fn.market_cap = NumberUtils.to_float(
                record.get(AppConsts.INTRINIO_KEY_CALCS_MARK_CAP))
            org_fn.revenue_growth = NumberUtils.to_float(
                record.get(AppConsts.INTRINIO_KEY_CALCS_REV_GRTH))
            org_fn.revenue_qq_growth = NumberUtils.to_float(
                record.get(AppConsts.INTRINIO_KEY_CALCS_REV_QQ_GRTH))
            org_fn.nopat_growth = NumberUtils.to_float(
                record.get(AppConsts.INTRINIO_KEY_CALCS_NOPAT_GRTH))
            org_fn.nopat_qq_growth = NumberUtils.to_float(
                record.get(AppConsts.INTRINIO_KEY_CALCS_NOTPAT_QQ_GRTH))
            org_fn.net_income_growth = NumberUtils.to_float(
                record.get(AppConsts.INTRINIO_KEY_CALCS_INCM_GRTH))
            org_fn.net_income_qq_growth = NumberUtils.to_float(
                record.get(AppConsts.INTRINIO_KEY_CALCS_INCM_QQ_GRTH))
            org_fn.free_cash_flow = NumberUtils.to_float(
                record.get(AppConsts.INTRINIO_KEY_CALCS_CSH_FLOW))
            org_fn.current_ratio = NumberUtils.to_float(
                record.get(AppConsts.INTRINIO_KEY_CALCS_CURR_RATIO))
            org_fn.debt_to_equity_ratio = NumberUtils.to_float(
                record.get(AppConsts.INTRINIO_KEY_CALCS_DE_RATIO))
            org_fn.pe_ratio = NumberUtils.to_float(
                record.get(AppConsts.INTRINIO_KEY_CALCS_PE_RATIO))
            org_fn.pb_ratio = NumberUtils.to_float(
                record.get(AppConsts.INTRINIO_KEY_CALCS_PB_RATIO))
            org_fn.div_payout_ratio = NumberUtils.to_float(
                record.get(AppConsts.INTRINIO_KEY_CALCS_DIV_PAYOUT_RATIO))
            org_fn.roe = NumberUtils.to_float(
                record.get(AppConsts.INTRINIO_KEY_CALCS_ROE))
            org_fn.roa = NumberUtils.to_float(
                record.get(AppConsts.INTRINIO_KEY_CALCS_ROA))
            BaseService._update()
        return "1"

    def import_from_csv_filedates(self) -> str:
        file: str = FileUtils.get_file(AppConsts.INCOME_STMT_FILE)
        records: List[Dict] = CsvUtils.parse_as_dict(file)
        for record in records:
            if not self.__is_valid_intrinio_record_for_filedates(record):
                continue
            symbol: str = record.get(AppConsts.INTRINIO_KEY_INC_STMT_TICKER)
            fiscal_period: str = record.get(
                AppConsts.INTRINIO_KEY_INC_STMT_FISC_PD)
            year: int = NumberUtils.to_int(
                record.get(AppConsts.INTRINIO_KEY_INC_STMT_FISC_YR))
            quarter: int = self.__get_quarter(fiscal_period)
            file_date: date = DateUtils.get_date(
                record.get(AppConsts.INTRINIO_KEY_INC_STMT_FILE_DTE),
                AppConsts.INTRINIO_FILE_DTE_FMT)
            if not file_date or quarter == 4:
                continue
            org_symbol: SM = self.__stock_service.get_symbol(
                symbol, AppConsts.INSTRUMENT_STOCK)
            if not org_symbol:
                continue
            org_fn: FN = self.__stock_service.get_financial(
                org_symbol.id, year, quarter)
            if not org_fn:
                continue
            org_fn.file_date = file_date
            BaseService._update()
        return "1"

    def __get_quarter(self, fiscal_period: str) -> int:
        if StringUtils.isNullOrWhitespace(fiscal_period):
            return None
        if fiscal_period.endswith(AppConsts.INTRINIO_PERIOD_SUFFIX_FY):
            return 4
        return NumberUtils.to_int(
            fiscal_period.replace(AppConsts.INTRINIO_PERIOD_PREFIX,
                                  '').replace(
                                      AppConsts.INTRINIO_PERIOD_SUFFIX_TTM,
                                      ''))

    def __is_valid_intrinio_record(self, record: Dict) -> bool:
        fiscal_period: str = record.get(
            AppConsts.INTRINIO_KEY_INC_STMT_FISC_PD)
        return record \
            and not StringUtils.isNullOrWhitespace(record.get(AppConsts.INTRINIO_KEY_INC_STMT_TICKER)) \
            and not StringUtils.isNullOrWhitespace(record.get(AppConsts.INTRINIO_KEY_INC_STMT_NAME)) \
            and not StringUtils.isNullOrWhitespace(fiscal_period) \
            and (fiscal_period.endswith(AppConsts.INTRINIO_PERIOD_SUFFIX_TTM) or fiscal_period.endswith(AppConsts.INTRINIO_PERIOD_SUFFIX_FY))

    def __is_valid_intrinio_record_for_filedates(self, record: Dict) -> bool:
        fiscal_period: str = record.get(
            AppConsts.INTRINIO_KEY_INC_STMT_FISC_PD)
        return record \
            and not StringUtils.isNullOrWhitespace(record.get(AppConsts.INTRINIO_KEY_INC_STMT_TICKER)) \
            and not StringUtils.isNullOrWhitespace(record.get(AppConsts.INTRINIO_KEY_INC_STMT_NAME)) \
            and not StringUtils.isNullOrWhitespace(fiscal_period) \
            and not fiscal_period.endswith(AppConsts.INTRINIO_PERIOD_SUFFIX_TTM) \
            and not fiscal_period.endswith(AppConsts.INTRINIO_PERIOD_SUFFIX_FY) \
            and not fiscal_period.endswith(AppConsts.INTRINIO_PERIOD_SUFFIX_YTD)

# endregion

# region YAHOO

    def import_from_csv_yahoo(self) -> str:
        BaseService._truncate(EPD)

        files: List[str] = FileUtils.get_files(AppConsts.ETF_PRICE_FOLDER,
                                               is_full=True)
        for file in files:
            symbol: str = FileUtils.get_wo_ext(FileUtils.get_base_name(file))
            org_symbol: SM = self.__stock_service.get_symbol(
                symbol, AppConsts.INSTRUMENT_ETF)
            if not org_symbol:
                continue
            records: List[Dict] = CsvUtils.parse_as_dict(file)
            models: List[Any] = []
            for record in records:
                models.append((
                    org_symbol.id,
                    DateUtils.get_date(record.get(AppConsts.YAHOO_KEY_DATE),
                                       AppConsts.YAHOO_DATE_FORMAT),
                    NumberUtils.to_float(record.get(AppConsts.YAHOO_KEY_OPEN)),
                    NumberUtils.to_float(record.get(AppConsts.YAHOO_KEY_HIGH)),
                    NumberUtils.to_float(record.get(AppConsts.YAHOO_KEY_LOW)),
                    NumberUtils.to_float(record.get(
                        AppConsts.YAHOO_KEY_CLOSE)),
                    NumberUtils.to_int(record.get(AppConsts.YAHOO_KEY_VOLUME)),
                ))
            BaseService._insert_bulk(EPD, models)
        return "1"
Esempio n. 11
0
from flask import Blueprint, request
from app_utils.model_utils import ModelUtils
from app_utils.string_utils import StringUtils
from app_utils.log_utils import LogUtils
from models.db.symbol_master import SymbolMaster
from models.request_models.chart_request import ChartRequest as CR
from models.response_models.response_model import ResponseModel
from services.stock_service import StockService

stock_api: Blueprint = Blueprint('stock_api', __name__)
__stock_service = StockService()


@stock_api.route('/get_symbols/<instrument>', methods=['GET'])
def get_symbols(instrument: str) -> str:
    return StringUtils.to_json(
        ResponseModel(__stock_service.get_symbols(instrument)))


@stock_api.route('/update_symbol', methods=['POST'])
def update_symbol() -> str:
    req: SymbolMaster = ModelUtils.get_obj(SymbolMaster(), request.get_json())
    return StringUtils.to_json(
        ResponseModel(__stock_service.update_symbol(req)))


@stock_api.route('/delete_old_prices', methods=['GET'])
def delete_old_prices() -> str:
    return StringUtils.to_json(
        ResponseModel(__stock_service.delete_old_prices()))
Esempio n. 12
0
 def __init__(self, *args, **kwargs):
   super(TestAlpacaClient, self).__init__(*args, **kwargs)
   self.__alpaca_client: AlpacaClient = AlpacaClient()
   self.__stock_service: StockService = StockService()
Esempio n. 13
0
 def __init__(self, *args, **kwargs):
   super(TestStockService, self).__init__(*args, **kwargs)
   self.__stock_service: StockService = StockService()
   self.__calc_service: CalcService = CalcService()