def update_values(n_clicks, value): if (n_clicks != None) & (value != None): lista, err = ek.get_data(value, 'RData') lista = lista.Instrument[~lista.Instrument.isnull()].values optionsInfo, err = ek.get_data(list(lista), [ 'TRADE_DATE', 'TRDPRC_1', "PUTCALLIND", "EXPIR_DATE", "STRIKE_PRC", "IMP_VOLT", "BKGD_REF" ]) optionsInfo = optionsInfo[optionsInfo.STRIKE_PRC.notnull()] optionsInfo = optionsInfo[optionsInfo.EXPIR_DATE.astype( 'datetime64') >= optionsInfo.TRADE_DATE.astype('datetime64').max()] spot, err = ek.get_data([optionsInfo.BKGD_REF.values[0]] + ['BRSELICD=CBBR'], ['TRADE_DATE', 'TRDPRC_1']) # print(optionsInfo.head()) optionsInfo['Delta'] = spot.TRDPRC_1.values[0] - optionsInfo.STRIKE_PRC optionsInfo_C = optionsInfo[optionsInfo.PUTCALLIND == 'CALL'] optionsInfo_P = optionsInfo[optionsInfo.PUTCALLIND != 'CALL'] RE = { "optionsInfo": optionsInfo.to_json(), "optionsInfo_C": optionsInfo_C.to_json(), "optionsInfo_P": optionsInfo_P.to_json(), "spot": spot.to_json() } return (json.dumps(RE)) else: return (None)
def update_output(n_clicks, value): lista, err = ek.get_data(value,'RData') lista=lista.Instrument[~lista.Instrument.isnull()].values optionsInfo, err = ek.get_data(list(lista),['TRADE_DATE','TRDPRC_1',"PUTCALLIND","EXPIR_DATE","STRIKE_PRC","BKGD_REF"]) optionsInfo=optionsInfo[optionsInfo.STRIKE_PRC.notnull()] #spot, err = ek.get_data(optionsInfo.BKGD_REF.values[0],['TRADE_DATE','TRDPRC_1',"PUTCALLIND","EXPIR_DATE","STRIKE_PRC","BKGD_REF"]) spot, err = ek.get_data([optionsInfo.BKGD_REF.values[0]]+['BRSELICD=CBBR'],['TRADE_DATE','TRDPRC_1']) optionsInfo['Delta']=spot.TRDPRC_1.values[0]-optionsInfo.STRIKE_PRC optionsInfo_C=optionsInfo[optionsInfo.PUTCALLIND=='CALL'] optionsInfo_P=optionsInfo[optionsInfo.PUTCALLIND!='CALL'] return (optionsInfo_C,optionsInfo_P,list(set(optionsInfo.EXPIR_DATE.values)))
def double_check_FY_data(iTicker, iPeriod, ioJsonData): if ioJsonData['IncomeStatement']['EBITDA'] == 0.0: df = ek.get_data(iTicker, 'TR.EBITDA(Period=' + iPeriod + ')', raw_output=True) ioJsonData['IncomeStatement']['EBITDA'] = FloatOrZero(df['data'][0][1]) if ioJsonData['IncomeStatement']['EBIT'] == 0.0: df = ek.get_data(iTicker, 'TR.EBIT(Period=' + iPeriod + ')', raw_output=True) ioJsonData['IncomeStatement']['EBIT'] = FloatOrZero(df['data'][0][1]) return ioJsonData
def thomson(self, tickers, fields, parameters=None): """tickers = 종목 코드에 대한 list fields = 불러오고자 하는 기능 parameters = 주로 기간에 대한 파라미터""" print( "Thomson starts #############################" ) ########## >> 텔레그램까지 자동화( eikon 실행은 작업 스케줄러) while True: try: if parameters == None: data = ek.get_data(tickers, fields=fields) data = pd.Series(data)[0] dates = ( pd.Series(ek.get_data(tickers, fields=["TR.CLOSEPRICE.date"]))[ 0 ]["Date"] .unique()[0] .split("T")[0] ) data["date"] = [dates for _ in range(len(tickers))] print(data) if len(data["Close Price"].dropna()) != 0: return data else: data = ek.get_data(tickers, fields=fields, parameters=parameters) data = pd.Series(data)[0] data["date"] = sum( [ list( pd.date_range( start=parameters["SDate"], end=parameters["EDate"], freq="B", ) ) for _ in range(len(tickers)) ], [], ) if len(data["Close Price"].dropna()) != 0: return data time.sleep(3) print("Restart sourcing") except: pass
def get_data(ric, start, end, fields, columns): """Generic Function to get data from Reuters, format the DataFrame to how we use the data in the application. :param ric: String ric :param start: String start date :param end: String end date :param fields: List fields to download :param columns: List column names to use in the new Dataframe :return: Dataframe """ log = logging.getLogger(__name__) log.debug('Get Data for {}, fields: '.format(ric, fields)) df, err = ek.get_data(ric, fields, parameters={ 'SDate': start, 'EDate': end }) # Transform df['Date'] = df.apply(lambda x: str(x['Date'])[0:10], axis=1) df.set_index('Date', inplace=True) df.index.names = [None] df.columns = columns return df
def get_bonds(iEikonTicker): print("bonds") aLabels = [ 'BetaWkly3Y', 'BetaWklyUp3Y', 'BetaWklyDown3Y', 'BetaWkly2Y', 'BetaWklyUp2Y', 'BetaWklyDown2Y' ] isins = [] isinListRaw = ek.get_data(iEikonTicker, 'TR.BondISIN', raw_output=True) for isin in isinListRaw["data"]: isins.append(isin[1]) df = ek.get_data(isins, [ 'TR.CouponRate', 'TR.FiMaturityDate', 'Tr.FiAssetTypeDescription', 'TR.FiMaturityStandardYield' ], raw_output=True) print()
def get_52_week_high_low(iEikonTicker): o52WHighLowJson = {} df = ek.get_data(iEikonTicker, ['TR.Price52WeekHigh', 'TR.Price52WeekLow'], raw_output=True) o52WHighLowJson["Price52WeekHigh"] = FloatOrZero(df['data'][0][1]) o52WHighLowJson["Price52WeekLow"] = FloatOrZero(df['data'][0][2]) return o52WHighLowJson
def Get_Data(eikon_iter_ric_list, date): OutShares, err = eikon.get_data(eikon_iter_ric_list, [ 'TR.CLOSEPRICE.calcdate', 'TR.CompanyMarketCap', 'TR.BIDPRICE', 'TR.ASKPRICE', 'TR.CLOSEPRICE', 'TR.Volume', 'TR.TotalReturn52Wk', 'TR.PriceToBVPerShare', 'TR.GrossProfit', 'TR.TotalAssetsReported' ], {'SDate': date}) return OutShares
def Get_Data(iter_ric_list): TS, err = eikon.get_data(iter_ric_list, ['TR.TSVWAP.calcdate', 'TR.TSVWAP'], { 'SDate': '1999-08-02', 'EDate': '2018-12-31', 'Frq': 'D' }) return TS
def Get_Data(iter_ric_list): OutShares, err = eikon.get_data( iter_ric_list, ['TR.BasicShrsOutAvg.calcdate', 'TR.BasicShrsOutAvg'], { 'SDate': '1999-08-31', 'EDate': '2018-12-31', 'Frq': 'M' }) return OutShares
def get_minority_interest(iEikonTicker): print("min interest") oMinInterest = {} df = ek.get_data(iEikonTicker, 'TR.MinorityInterestNonRedeemable', raw_output=True) oMinInterest["MinorityInterest"] = FloatOrZero(df['data'][0][1]) return oMinInterest
def get_30_day_volume(iEikonTicker): oAccumulatedVol = 0 volumes = ek.get_data(iEikonTicker, 'TR.ACCUMULATEDVOLUME(SDate=0,EDate=-29,Frq=D)', raw_output=True) for vol in volumes['data']: oAccumulatedVol += FloatOrZero(vol[1]) return oAccumulatedVol
def generate_queries(quote_date, ccy, instruments, instrument, sources): import QuantLib as ql commands = list() source = sources[instrument] val = instruments[instrument] if instrument == 'Depo': expiries = ['TN', 'SN', '1M', '3M'] instruments = ['USD{}{}='.format(expiry, val) for expiry in expiries] elif instrument == 'Fut': expiries = list() current_date = ql.DateParser_parse(quote_date, '%Y-%m-%d') for i in range(8): expiries.append(ql.IMM_nextCode(current_date)) current_date = ql.IMM_nextDate(current_date) instruments = ['{}{}'.format(val, expiry) for expiry in expiries] elif instrument == 'Swap': expiries = [ '3Y', '4Y', '5Y', '6Y', '7Y', '8Y', '9Y', '10Y', '15Y', '20Y', '25Y', '30Y' ] instruments = [ 'USD{}{}={}'.format(val, expiry, source) for expiry in expiries ] elif instrument == 'Swaption': expiries = [ '1M', '3M', '6M', '1Y', '2Y', '3Y', '4Y', '5Y', '6Y', '7Y', '8Y', '9Y', '10Y', '15Y', '20Y', '25Y', '30Y' ] tenors = [ '1Y', '2Y', '3Y', '4Y', '5Y', '6Y', '7Y', '8Y', '9Y', '10Y', '15Y', '20Y', '25Y', '30Y' ] instruments = [ 'USD{}{}X{}={}'.format(val, expiry, tenor, source) for expiry in expiries for tenor in tenors ] result, err = ek.get_data(instruments, ['CF_LAST']) #instruments = ['USD1YX1YN{}=R'.format(i+1) for i in range(13)] #result, err = ek.get_data(instruments, ['CF_LAST']) #print(result) for i in range(len(result)): if instrument != 'Swaption': expiry, tenor, quote = expiries[i], '', result.iloc[ i, :]['CF_LAST'] else: bucket = result.iloc[i, :]['Instrument'].split('=')[0][3:].split( 'X') expiry, tenor, quote = bucket[0], bucket[1], result.iloc[ i, :]['CF_LAST'] commands.append( "INSERT INTO \"IRInstruments\" VALUES (Date('{}'), '{}', '{}', '{}', '{}', '{}', {})" .format(quote_date, ccy, instrument, source, expiry, tenor, quote)) return commands
def retrieve_fiscal_year_data(iEikonTicker): print("retrieve_fiscal_year_data") aFiscalYears = ['FY-4', 'FY-3', 'FY-2', 'FY-1', 'FY0'] numberOfYears = len(aFiscalYears) oListJson = {} aFYDataDict = collections.defaultdict(dict) aFYDataDict["Estimated"] = "false" #Obtain last reported Fiscal Year date df = ek.get_data(iEikonTicker, 'TR.EBITDA(Period=FY0).periodenddate', raw_output=True) #'data': [['AAPL.O', '2018-09-29']] aLastFYEnd = df['data'][0][1].split("-") #['2018', '09', '29'] if aLastFYEnd == ['']: df = ek.get_data(iEikonTicker, 'TR.Revenue(Period=FY0).periodenddate', raw_output=True) aLastFYEnd = df['data'][0][1].split("-") if aLastFYEnd == ['']: print('ERROR NO SMART DATE PERIOD END DATE') aLastFYEnd = datetime( int(aLastFYEnd[0]), int(aLastFYEnd[1].lstrip("0")), int(aLastFYEnd[2].lstrip("0"))) #datetime.datetime(2018, 9, 29, 0, 0) aFY0 = aLastFYEnd.year - len(aFiscalYears) + 1 #2018-5+1=2014 aLabels, df = retrieve_eikon_reports(iEikonTicker, 'FY', str(numberOfYears - 1)) for indx, fy in enumerate(aFiscalYears, start=0): # 0 FY-4, 1 FY-3... #NOTE:Historic fiscal year price close #Get array of all data, first elem is the ticker which is not needed, last 4 are the period end dates aDfLen = len(df['data'][0]) - 5 aFYJson = {"FY" + str(aFY0): {}} for idx in range(0, aDfLen): aFYDataDict[aLabels[idx][1]][aLabels[idx][0]] = FloatOrZero( df['data'][indx][idx + 1] ) #'data': [['AAPL.O', 39510000000, 60503000000], ['AAPL.O', 53394000000, 81730000000]... double_check_FY_data(iEikonTicker, fy, aFYDataDict) aFYJson["FY" + str(aFY0)] = dict(aFYDataDict) oListJson.update(copy.deepcopy(aFYJson)) aFY0 = aFY0 + 1 return oListJson
def convert_symbology(self, symbol, target_symbol_type = 'TR.ISIN'): converted_result = True try: response = ek.get_data(symbol,target_symbol_type, raw_output = True) if 'error' in response or not response['data'][0][1]: # The get_data can returns both 'error' and just empty/null result converted_result = False return converted_result, response except Exception as ex: logging.error('Data API: get_data exception failure: %s' % ex) return False, None
def get_fiscal_year_dates(iEikonTicker): print("FY dates") oFY = {} df = ek.get_data(iEikonTicker, 'TR.EBITDA(Period=FY0).periodenddate', raw_output=True) # 'data': [['SJM.N', '2019-04-30']] fulldate = df['data'][0][1].split("-") if fulldate == ['']: df = ek.get_data(iEikonTicker, 'TR.Revenue(Period=FY0).periodenddate', raw_output=True) fulldate = df['data'][0][1].split("-") if fulldate == ['']: print('ERROR NO FISCAL YEAR END DATE USING EBITDA OR REVENUE') month = fulldate[1].lstrip("0") aMonthName = calendar.month_abbr[int(month)].upper() aMonthDay = df['data'][0][1].split("-")[2] oFY["FYEndDate"] = (aMonthDay + '-' + aMonthName) return oFY
async def time(websocket, path): ric_codes = [] while True: if not ric_codes: rst = requests.get(data_url) ric_codes = json.loads(rst.text)['data'] ric_codes = [str(code) for code in ric_codes] # ric_codes = await websocket.recv() data, err = eikon.get_data(instruments=ric_codes, fields=['CF_LAST']) message = ','.join(['%.4f' % d for d in data['CF_LAST']]) await websocket.send(message) await asyncio.sleep(0.1)
def get_data(rics: list, fields: list): """ Eikon API call for data type file (not time series). Print any errors. :param rics: List of RIC:s to get. :param fields: List fields to get. :return: None. """ data, err = ek.get_data(rics, fields) if err: logger.error(err) return data
def get(self, fs, params=''): # Check UUID in Bearer of API request. This is a simple wrapper. token = request.headers.get('Authorization', None) if token is None: return None method, tokenstr = token.split() if method.lower() == "bearer" and tokenstr == conf['pywrapper']['apikey']: df = ek.get_data(instruments='0#HSI*.HF', fields=str(fs).split(','), parameters=params, raw_output=True) return jsonify(df) else: return None
def getdata(): rqst = request.get_json() try: rst = eikon.get_data(instruments=rqst['instruments'], fields=rqst['fields'], parameters=rqst['parameters'], raw_output=True) return jsonify(data=rst) except Exception as err: webapp.logger.warn(err) return abort(500)
def retrieve_estimated_fiscal_year_data(iEikonTicker): print("retrieve_estimated_fiscal_year_data") aFiscalYears = ['FY1', 'FY2', 'FY3', 'FY4'] aFYDataDict = collections.defaultdict(dict) aFYDataDict["Estimated"] = "true" oListJson = {} df = ek.get_data(iEikonTicker, 'TR.EPSMean(Period=FY1).periodenddate', raw_output=True) aLastFYEnd = df['data'][0][1].split("-") if aLastFYEnd == ['']: df = ek.get_data(iEikonTicker, 'TR.EpsSmartEst(Period=FY1).periodenddate', raw_output=True) aLastFYEnd = df['data'][0][1].split("-") if aLastFYEnd == ['']: df = ek.get_data(iEikonTicker, 'TR.EBITDAMean(Period=FY1).periodenddate', raw_output=True) aLastFYEnd = df['data'][0][1].split("-") if aLastFYEnd == ['']: print('ERROR NO SMART DATE PERIOD END DATE') aLastFYEnd = datetime(int(aLastFYEnd[0]), int(aLastFYEnd[1].lstrip("0")), int(aLastFYEnd[2].lstrip("0"))) aFY1 = aLastFYEnd.year #NOTE:Estimated fiscal year price close aLabels, df = retrieve_eikon_estimates(iEikonTicker, 'FY', str(len(aFiscalYears))) for indx, fy in enumerate(aFiscalYears, start=0): #Get array of all data, first parameter is ticker, it isnt needed aDfLen = len(df['data'][0]) - 5 aFYJson = {"FY" + str(aFY1): {}} for idx in range(0, aDfLen): aFYDataDict[aLabels[idx][1]][aLabels[idx][0]] = FloatOrZero( df['data'][indx][idx + 1]) aFYJson["FY" + str(aFY1)] = dict(aFYDataDict) oListJson.update(copy.deepcopy(aFYJson)) aFY1 = aFY1 + 1 return oListJson
def reuters_eikon_data_scraper(instruments: list, fields: list, properties:dict, api_key:str): df, err = None, None ek.set_app_key(api_key) try: df, err = ek.get_data(instruments, fields, properties, field_name=True, raw_output=False) if err is not None: err = {'error_type': 'REUTERS', 'error_message': str(err), 'req_instruments': instruments, 'req_fields': fields, 'req_properties': properties} else: df.columns = [i.replace('.', '_') for i in df.columns.tolist()] except Exception as error: err = {'error_type': 'PyREUTERS', 'error_message': str(error).replace('\n', ';').encode(), 'req_instruments': instruments, 'req_fields': fields, 'req_properties':properties} finally: return df, err
def reportdate(): rics = request.get_json() try: result = eikon.get_data(instruments=rics, fields='TR.ExpectedReportDate')[0] refined = dict( zip(result['Instrument'], result['Expected Report Date'])) webapp.logger.info("{} | {}".format(len(rics), len(refined))) return jsonify(data=refined) except Exception as err: webapp.logger.warn(err) return abort(500)
def get_120_month_share_price(iEikonTicker): print("monthly updates") o120MonthPrice = {"120MonthSharePrice": {}} aJson = {} aPrices = ek.get_data(iEikonTicker, [ 'TR.PriceClose(SDate=0,EDate=-119,Frq=CM)', 'TR.PriceClose(SDate=0,EDate=-119,Frq=CM).calcdate' ], raw_output=True) for aPrice in aPrices['data']: aJson["PriceClose"] = FloatOrZero(aPrice[1]) o120MonthPrice["120MonthSharePrice"][str( aPrice[2][:-3])] = copy.deepcopy(aJson) return o120MonthPrice
def get_competitors(iEikonTicker): # ISIN (or CUSIP) represent a financial instrument, whereas RICs represent a financial instrument on a specific market print("competitors") aIndex = 1 oDailyJson = {"Competitors": []} aJson = {} screener_exp = "SCREEN(U(IN(Peers('" + iEikonTicker + "'))))" peers = ek.get_data(instruments=[screener_exp], fields=['TR.CompanyName', 'TR.RICCode'], raw_output=True) for company in peers["data"]: aJson["Name"] = company[1] aJson["EikonTicker"] = company[2] oDailyJson["Competitors"].append(copy.deepcopy(aJson)) aIndex += 1 return oDailyJson
def get_eikon_ohlcv_oi(eikon_symbol,exchange_symbol,start_date,end_date): """ Fetch daily open, high, low close, open interest data for "platform_symbol". """ assert type(start_date) is str, "start_date is not a string: %r" % start_date assert type(end_date) is str, "start_date is not a string: %r" % end_date try: tmp_ohlcv = ek.get_timeseries(eikon_symbol,["open","high","low","close","volume"],start_date=str(start_date), end_date=str(end_date)) except ek.EikonError: return pd.DataFrame() tmp_ohlcv.insert(0,'exchange_symbol',exchange_symbol) e = ek.get_data(eikon_symbol, ['TR.OPENINTEREST.Date', 'TR.OPENINTEREST'], {'SDate':str(start_date),'EDate':str(end_date)}) tmp_oi = pd.DataFrame({'open_interest': e[0]['Open Interest'].values}, index = pd.to_datetime(e[0]['Date'].values)) tmp = pd.merge(tmp_ohlcv,tmp_oi,left_index=True,right_index=True) return tmp
def get_betas(iEikonTicker): print("betas") oBetasJson = {"Betas": {}} aStartIndex = 1 aLabels = [ 'BetaWkly3Y', 'BetaWklyUp3Y', 'BetaWklyDown3Y', 'BetaWkly2Y', 'BetaWklyUp2Y', 'BetaWklyDown2Y' ] df = ek.get_data(iEikonTicker, [ 'TR.BetaWkly3Y', 'TR.BetaWklyUp3Y', 'TR.BetaWklyDown3Y', 'TR.BetaWkly2Y', 'TR.BetaWklyUp2Y', 'TR.BetaWklyDown2Y' ], raw_output=True) for betas in aLabels: oBetasJson["Betas"][betas] = FloatOrZero(df['data'][0][aStartIndex]) aStartIndex += 1 return oBetasJson
def retrieve_monthly_assets_total_returns(date_from, date_to, assets_ric_list): if date_from >= date_to: raise Exception("Dates are wrong") if len(assets_ric_list) == 0: raise Exception("At least one RIC needed in the RICs list") ek.set_app_key("94baceedc0c24ae8961456ae2b67bc72532e997f") start_date = date_from end_date = date_to timeline = [] next_from_date = start_date.replace(day=1) next_to_date = (start_date + rd.relativedelta(months=1)) + rd.relativedelta(days=-1) next_time_slot = (next_from_date, next_to_date) while next_time_slot[1] < end_date: timeline.append(next_time_slot) next_from_date = timeline[-1][1] + rd.relativedelta(days=1) next_to_date = (next_from_date + rd.relativedelta(months=1)) + rd.relativedelta(days=-1) next_time_slot = (next_from_date, next_to_date) total_return_percentage_all = {} for target_asset in assets_ric_list: total_return_percentage_all[target_asset] = {} total_return_percentage_all[target_asset]["timeline"] = [] for timeslot in timeline: start_time = time.time() i = timeline.index(timeslot) tl = len(timeline) f = dt.datetime.strftime(timeslot[0], "%Y-%m-%d") t = dt.datetime.strftime(timeslot[1], "%Y-%m-%d") o = ek.get_data(assets_ric_list, ['TR.TotalReturn'], {'SDate': f, 'EDate': t}) o_assets_list = o[0]["Instrument"].to_list() for target_asset in assets_ric_list: index_of_target_asset = o_assets_list.index(target_asset) try: to_store = ((f, t), float(o[0]["Total Return"][index_of_target_asset]) / 100) except ValueError: to_store = ((f, t), np.nan) total_return_percentage_all[target_asset]["timeline"].append(to_store) end_time = time.time() msg = "Loading from Eikon ({:d} of {:d}, {:.2f}%) (remaining time: {:.2f} seconds)" print(msg.format(i, tl, 100 * i / tl, (end_time - start_time)*(tl-i))) return total_return_percentage_all
def get_daily_updates(iEikonTicker): oDailyJson = {"DailyUpdated": {}} aStartIndex = 1 aLabels = [ 'CompanyMarketCap', 'EV', 'SharePrice', 'DailyVolume', 'PE', 'SharesOutstanding', 'SIShortInterest', 'TotalReturnYTD' ] df = ek.get_data(iEikonTicker, [ 'TR.CompanyMarketCap', 'TR.EV', 'CF_LAST', 'TR.Volume', 'TR.PE', 'TR.SharesOutstanding', 'TR.SIShortInterest', 'TR.TotalReturnYTD' ], raw_output=True) for data in aLabels: oDailyJson["DailyUpdated"][data] = FloatOrZero( df['data'][0][aStartIndex]) aStartIndex += 1 oDailyJson["DailyUpdated"]["30DayVolume"] = get_30_day_volume(iEikonTicker) return oDailyJson
def get_365_day_share_price(iEikonTicker, iDateRange=364): print("365 daily price") o365DayPrice = {"365DaySharePrice": {}} aJson = {} aPrices = ek.get_data(iEikonTicker, [ 'TR.PriceClose(SDate=0,EDate=-' + iDateRange + ',Frq=D)', 'TR.PriceOpen(SDate=0,EDate=-' + iDateRange + ',Frq=D)', 'TR.PriceHigh(SDate=0,EDate=-' + iDateRange + ',Frq=D)', 'TR.PriceLow(SDate=0,EDate=-' + iDateRange + ',Frq=D)', 'TR.PriceClose(SDate=0,EDate=-' + iDateRange + ',Frq=D).calcdate' ], raw_output=True) for aPrice in aPrices['data']: aJson["PriceClose"] = FloatOrZero(aPrice[1]) aJson["PriceOpen"] = FloatOrZero(aPrice[2]) aJson["PriceHigh"] = FloatOrZero(aPrice[3]) aJson["PriceLow"] = FloatOrZero(aPrice[4]) o365DayPrice["365DaySharePrice"][str(aPrice[5])] = copy.deepcopy(aJson) return o365DayPrice