-- new 03/03/2006 -- Расчет оценочной стоимости ЦБ -- -- Оценочная стоимостью ЦБ признается равным (кол-во ЦБ * котировка). -- Если котировка до первой покупки не найдена, то оценочной стоимостью считается сальдо по 58.1 счету по этой ЦБ -- на 58.1 счету, хранятся покупки ЦБ, без учета комиссий и переоценки -- Поиск котировки возможен тремя способами: -- 1. Если в срезе не задана площадка и у фонда значение классификатора "Выбор площадки при определении котировки" -- равно "MAX" то ищется максимальная котировка по всем площадкам (коды RTS,MICEX) -- 2. Если в срезе не задана площадка, у фонда значение классификатора "Выбор площадки при определении котировки" -- равно "ONE" то котировка ищется на площадке указанной в расширенном классификаторе ЦБ "STOCK_RATE_PLACE" -- и если в площадке классификатор не указан, то ищется по площадке указанной в срезе. -- 3. Если в срезе задана площадка и у фонда значение классификатора "Выбор площадки при определении котировки" -- равно "TWO", то котировка ищется на площадках с кодами "MMVB", "RTS" в случае отсутствия котировки на первой площадке -- поиск идет по второй площадке. Первой площадкой является та, что выбрана в срезе, если же в срезе площадка -- не задана, то первой считается та, что указана в расширенном классификаторе ЦБ "STOCK_RATE_PLACE" -- Если значение классификатора "Выбор площадки при определении котировки" не указано, то считается что фонду присвоено -- значение "TWO" - значение по умолчанию. -- Поиск котировок ведется за период с первой покупки ЦБ в фонде до даты построения среза. create procedure dbo.%PROC% @stock_id numeric(18,0), -- Ценная бумага @fund_id numeric(18,0), -- Фонд @place_id numeric(18,0), -- Площадка котировок @check_date datetime, -- Дата определения стоимости ЦБ @stock_qty money, -- Кол-во ЦБ @rate_date datetime out, -- Фактическая дата котировки @is_rate int out, -- Тип котировки (0 - прочая, 1 - признаваемая) @stock_rate decimal(18,8) out, -- Котировка ЦБ @coupon_rate decimal(18,8) out, -- Купон ЦБ @stock_sum money out, -- Оценочная стоимость ЦБ @coupon_sum money out -- Оценочная стоимость купона as declare @first_date_rate datetime, -- Дата первой покупки ЦБ @subconto_stock_id numeric(18,0), -- Тип субконто "STOCK_EMIS" @acc581_id numeric(18,0), -- Счет 58.1 @plan_id numeric(18,0), -- План счетов "PIF_ACCOUNT" @plan2partner_id numeric(18,0), -- Владелец плана счетов @rate_cur_id numeric(18,0), -- Валюта котировки @stock_rate_cur decimal(18,8), -- Котировка ЦБ @coupon_rate_cur decimal(18,8), -- Купон ЦБ @subconto_str varchar(255), -- Эффективная строка субконто (для SALDO) @saldo_sum decimal(18,8), -- Остаток ЦБ (сумма по балансу) @saldo_qty decimal(18,8), -- Остаток ЦБ (кол-во) @rur_cur_id numeric(18,0), -- Валюта "Российский рубль" @place_cur_id numeric(18,0), -- Валюта площадки котировок @convert_value decimal(18,8), -- Курс целевой валюты к исходной (для CONVERT_SUM_DEC) @convert_date datetime, -- Дата курса (для CONVERT_SUM_DEC) @stock_rate_rur decimal(36,12), -- Котировка ЦБ в рублях (используется при конвертации котировки в Рубли) @coupon_rate_rur decimal(36,12), -- Котировка купона в рублях (используется при конвертации котировки в Рубли) @stock_type_id numeric(18,0), -- Тип ЦБ @place_b_id numeric(18,0), -- Площадка котировок для поиска (начало) @place_e_id numeric(18,0), -- Площадка котировок для поиска (конец) @class_value_code varchar(255), -- Код площадки из расширенного классификатора в ЦБ @class_comment varchar(255), -- Кол-во знаков округления из комментария в расширенном классификаторе ЦБ (varchar) @steps int, -- Кол-во обрабатываемых площадок @place_in_rate_check varchar(10), -- Способ поиска котировки @first_place_id numeric(18,0), -- 1-ая, переданная в процедуру площадка котировок @oper_date datetime, -- @new_place_id numeric(18,0), -- @class_round int -- Кол-во знаков округления из комментария в расширенном классификаторе ЦБ (int) select @subconto_stock_id=.SUBCTYPE_FROM_CODE('STOCK_EMIS') select @plan_id=.PLAN('PIF_ACCOUNT') select @acc581_id=.SD_ACCID_FROM_EFFNO(@plan_id,'58.1') select @steps=1 select @rur_cur_id=.CUR('RUR') select @stock_type_id=t_stock_types.stock_type_id from td_stock_emis, t_stock_types where td_stock_emis.id = @stock_id and td_stock_emis.stock_type_id = t_stock_types.id -- Владелец плана счетов select @plan2partner_id=t_plans2partner.id from t_plans2partner, t_items, t_states where t_plans2partner.plan_id = @plan_id and t_plans2partner.partner_id = @fund_id and t_plans2partner.id = t_items.id and t_items.state_id = t_states.id and t_states.class_id = 0 -- Первая покупка ЦБ в фонде select @first_date_rate=min(t_oper_list.op_date) from t_oper_list, t_oper_subconto where t_oper_subconto.subconto_type_id = @subconto_stock_id and t_oper_subconto.item_id = @stock_id and t_oper_subconto.id = t_oper_list.id and t_oper_list.deb_or_cred = 1 and t_oper_list.acc_id = @acc581_id and t_oper_list.partner2plan_id = @plan2partner_id and t_oper_list.op_date < dateadd(dd,1,@check_date) -- Нормализация даты (срезаем время) select @first_date_rate=.DATE_NORM(@first_date_rate,B) if @first_date_rate is null select @first_date_rate=convert(datetime,'01/01/1980',103) select @place_in_rate_check=.GET_CLASS_VALUE_CODE_FOR_ITEM(@fund_id,'PLACES_IN_RATE_CHECK','TWO') if @place_in_rate_check is null select @place_in_rate_check='TWO' select @place_in_rate_check=upper(@place_in_rate_check) select @first_place_id=@place_id -- площадка из классификатора для ЦБ if @place_id is null and @place_in_rate_check <> 'MAX' begin exec ap_getclassvalue_code @stock_id, 'STOCK_RATE_PLACE', null, @fund_id, @class_value_code out, @class_comment out select @place_id=td_rate_places.id from td_rate_places where upper(td_rate_places.place_code) = upper(@class_value_code) and .ITEMS_EXISTS_BY_TYPE(td_rate_places.id,'RATE_PLACES') if isnull(@class_comment,'') <> '' select @class_round=convert(int,@class_comment) end -- Если в срезе площадка не указана, то первой считается та, что указана в классификаторе. if @first_place_id is null select @first_place_id=@place_id if @place_id is null begin select @place_b_id=-999999999999999998 select @place_e_id=999999999999999999 end else begin select @place_b_id=@place_id select @place_e_id=@place_id end select @oper_date=@check_date -- Котировка ЦБ if @place_in_rate_check = 'MAX' begin while @oper_date >= @first_date_rate begin if isnull(@stock_rate_cur,0) = 0 select @stock_rate_cur=max(tb_stock_rates.acknowledged_price), @is_rate=max(tb_stock_rates.rate_type), @rate_date=max(tb_stock_rates.rate_date), @rate_cur_id=max(tb_stock_rates.rate_cur_id), @place_id=max(tb_stock_rates.rate_place_id) from tb_stock_rates, td_rate_places where tb_stock_rates.rate_place_id between @place_b_id and @place_e_id and tb_stock_rates.stock_id = @stock_id and tb_stock_rates.rate_date = @oper_date and .ITEMS_EXISTS(tb_stock_rates.id) and td_rate_places.id = tb_stock_rates.rate_place_id and upper(td_rate_places.place_code) in ('RTS','MICEX') select @oper_date=dateadd(dd,-1,@oper_date) end end else if @place_in_rate_check = 'ONE' begin if @place_id is null select @place_id=@first_place_id while @oper_date >= @first_date_rate begin if isnull(@stock_rate_cur,0) = 0 select @stock_rate_cur=tb_stock_rates.acknowledged_price, @is_rate=tb_stock_rates.rate_type, @rate_date=tb_stock_rates.rate_date, @rate_cur_id=tb_stock_rates.rate_cur_id, @place_id=tb_stock_rates.rate_place_id from tb_stock_rates where tb_stock_rates.rate_place_id = @place_id and tb_stock_rates.stock_id = @stock_id and tb_stock_rates.rate_date = @oper_date and .ITEMS_EXISTS(tb_stock_rates.id) select @oper_date=dateadd(dd,-1,@oper_date) end end else if @place_in_rate_check = 'TWO' begin while @oper_date >= @first_date_rate begin select @steps=1 if @first_place_id is not null select @place_id=@first_place_id while @steps <= 2 begin if isnull(@stock_rate_cur,0) = 0 select @stock_rate_cur=tb_stock_rates.acknowledged_price, @is_rate=tb_stock_rates.rate_type, @rate_date=tb_stock_rates.rate_date, @rate_cur_id=tb_stock_rates.rate_cur_id, @place_id=tb_stock_rates.rate_place_id from tb_stock_rates where tb_stock_rates.rate_place_id = @place_id and tb_stock_rates.stock_id = @stock_id and tb_stock_rates.rate_date = @oper_date and .ITEMS_EXISTS(tb_stock_rates.id) if isnull(@stock_rate_cur,0) = 0 begin select @new_place_id=td_rate_places.id from td_rate_places where upper(td_rate_places.place_code) in ('RTS','MICEX') and .ITEMS_EXISTS_BY_TYPE(td_rate_places.id,'RATE_PLACES') and td_rate_places.id <> @place_id select @place_id=@new_place_id end select @steps=@steps+1 end select @oper_date=dateadd(dd,-1,@oper_date) end end select @place_cur_id=(select td_rate_places.cur_id from td_rate_places where id=@place_id) -- Оценочная стоимость по остатку if @stock_rate_cur is null begin select @subconto_str=null .SUBC_STR_ADD(@subconto_str, 'STOCK_EMIS', @stock_id) -- Дебетовое сальдо по 58.1 счету и заданной ЦБ .SALDO(@fund_id, 'PIF_ACCOUNT', @check_date, '58.1', @subconto_str, N, 'D', @saldo_sum, @saldo_qty) -- Нормализация сумм для предотвращения деления на ноль if isnull(@saldo_sum,0) = 0 select @saldo_sum=0 if isnull(@saldo_qty,0) = 0 select @saldo_qty=1 -- select @stock_rate_cur=convert(decimal(18,8),(convert(double precision, @saldo_sum) / convert(double precision, @saldo_qty))) -- Дата первой покупки, если котировка не найдена -- select @rate_date=isnull(@rate_date,@check_date) -- Округление оценочной стоимости select @stock_sum=convert(money,@saldo_sum,2) select @is_rate=-1 end -- Если котировка найдена, то купон ищем на той же площадке, иначе ищем на первой площадке if @stock_rate_cur is null select @place_id=@first_place_id -- Поиск НКД select @coupon_rate_cur=tb_stock_rates.coupon_rate, @place_cur_id=tb_stock_rates.rate_cur_id from tb_stock_rates where tb_stock_rates.rate_place_id = @place_id and tb_stock_rates.stock_id = @stock_id and tb_stock_rates.rate_date = @check_date and .ITEMS_EXISTS(tb_stock_rates.id) -- Округление котировки if isnull(@stock_rate_cur,0) <> 0 begin -- Если в классификаторе ЦБ задано кол-во знаков округления котировки, то сначал округлим ее if @class_round is not null select @stock_rate_cur=round(@stock_rate_cur,@class_round) select @rate_cur_id=isnull(@rate_cur_id,@place_cur_id) select @rate_cur_id=isnull(@rate_cur_id,@rur_cur_id) -- Конвертация котировки в Российский рубль if @rur_cur_id = @rate_cur_id select @stock_rate_rur=@stock_rate_cur else begin .CONVERT_SUM_DEC(@rate_cur_id, @rur_cur_id, @check_date, 0, @stock_rate_cur, @stock_rate_rur, @convert_value, @convert_date) end -- Округление котировки (только при установленном классификаторе "TYPE_ROUND_RATES_IN_CALC") -- в противном случае, округлять следует после вычсилений с использованием данной котировки if .GET_CLASS_VALUE_CODE_FOR_ITEM(@fund_id,'TYPE_ROUND_RATES_IN_CALC','BEFORE') = 'BEFORE' begin .PIF_ROUND_RATE(@fund_id, @stock_rate_rur, @stock_rate_rur) end -- Оценочная сумма (кол-во * котировку) select @stock_sum=convert(money,round((convert(decimal(36,12),@stock_qty) * @stock_rate_rur),2)) -- Округление котировки до кол-ва знаков указанных в фонде .PIF_ROUND_RATE(@fund_id, @stock_rate_rur, @stock_rate_rur) -- Определение типа котировки if isnull(@is_rate,0) not in (0,1) select @is_rate=1 -- Передача значения в out-переменную select @stock_rate=convert(decimal(18,8),@stock_rate_rur) end else select @stock_rate=0 -- Расчет купона, если котировка купона не найдена (@stock_type_id = 2 <- базовый тип ЦБ "Облигация") if isnull(@coupon_rate_cur,0) = 0 and @stock_type_id = 2 begin .PIF_CALC_COUPON(@stock_id, @check_date, @coupon_rate_cur, @rate_cur_id) end -- Округление купона if @coupon_rate_cur is not null begin select @rate_cur_id=isnull(@rate_cur_id,@place_cur_id) select @rate_cur_id=isnull(@rate_cur_id,@rur_cur_id) -- Конвертация купона в Российский рубль if @rur_cur_id = @rate_cur_id select @coupon_rate_rur=@coupon_rate_cur else begin .CONVERT_SUM_DEC(@rate_cur_id, @rur_cur_id, @check_date, 0, @coupon_rate_cur, @coupon_rate_rur, @convert_value, @convert_date) end -- Округление купона (только при установленном классификаторе "TYPE_ROUND_RATES_IN_CALC") -- в противном случае, округлять следует после вычсилений с использованием данного купона if .GET_CLASS_VALUE_CODE_FOR_ITEM(@fund_id,'TYPE_ROUND_RATES_IN_CALC','BEFORE') = 'BEFORE' begin .PIF_ROUND_RATE(@fund_id, @coupon_rate_rur, @coupon_rate_rur) end -- Округление купона до кол-ва знаков указанных в фонде .PIF_ROUND_RATE(@fund_id, @coupon_rate_rur, @coupon_rate_rur) -- купон округляется всегда до двух знаков SELECT @coupon_rate = ROUND(@coupon_rate_rur, 2) SELECT @coupon_rate_rur = ROUND(@coupon_rate_rur, 2) -- Оценочная сумма (кол-во * купон) select @coupon_sum = ROUND(isnull(convert(money,round((convert(decimal(36,12),@stock_qty) * @coupon_rate_rur),2)),0), 2) -- Передача значения в out-переменную -- select @coupon_rate=convert(decimal(18,8),@coupon_rate_rur) end if @rate_date <> @check_date or @is_rate=-1 select @is_rate=0 else select @is_rate=1