powered by simpleCommunicator - 2.0.52     © 2025 Programmizd 02
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Задача нахождения равновесной цены спроса и предложения
14 сообщений из 14, страница 1 из 1
Задача нахождения равновесной цены спроса и предложения
    #39946128
Energomarket
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Доброго времени суток.
Прошу помощи оптимизировать запрос.
Есть исходная таблица ORDERS с заявками на покупку/продажу (любого товара), которая содержит следующие поля:
OPER - 1 - заявка на покупку, 2 - заявка на продажу
VAL_ORDER - объем покупки/продажи
PRICE_ORDER - цена покупки/продажи (для покупателей (OPER = 1) - максимальная, для продавцов (OPER = 2) - минимальная)
-1 - минимальная цена рынка
10000000 - максимальна цена рынка
Задача: найти равновесную стоимось и объем рынка.
Ниже запрос, который для каждой цены на рынке определяет объем покупки и объем продажи.
В случае совпадения объемов - это будет равновесная цена покупки/продажи (спроса и предложения)
Если совпадения не произошло то в случае превышения объема продажи от объема покупки (подряд проверять все записи курсора) - необходимо найти точку пересечения (анализировать точки).
Если не произошло и превышения объема продажи от объема покупки - то продается весь объем, который готовы забрать покупатели (последняя запись курсора).

Думаю что запрос построен не оптимальным способом (время его отработки при больших объемах заявок и циклических вызовах будет слишком большим):
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
 
with
  ORDERS as
  (
    select 100 as PRICE_ORDER, 3 as VAL_ORDER, 1 OPER from dual union all
    select 80 as PRICE_ORDER, 2 as VAL_ORDER, 1 OPER from dual union ALL
    select 70 as PRICE_ORDER, 4 as VAL_ORDER, 1 OPER from dual union ALL
    select 60 as PRICE_ORDER, 4 as VAL_ORDER, 1 OPER from dual union ALL
    select 20 as PRICE_ORDER, 5 as VAL_ORDER, 1 OPER from dual union ALL
    select 50 as PRICE_ORDER, 4 as VAL_ORDER, 2 OPER from dual union ALL
    select 30 as PRICE_ORDER, 5 as VAL_ORDER, 2 OPER from dual union ALL
    select 40 as PRICE_ORDER, 2 as VAL_ORDER, 2 OPER from dual union ALL
    select 60 as PRICE_ORDER, 6 as VAL_ORDER, 2 OPER from dual union ALL
    select 10 as PRICE_ORDER, 1 as VAL_ORDER, 2 OPER from dual union ALL
    select 70 as PRICE_ORDER, 2 as VAL_ORDER, 2 OPER from dual union ALL
    select 50 as PRICE_ORDER, 1 as VAL_ORDER, 2 OPER from dual 
  )
select PR.PRICE_ORDER,
(select MAX(PR1.SUM_VAL) from 
(select PRICE_ORDER, NVL(LEAD(PRICE_ORDER) OVER (order by PRICE_ORDER desc), -1) PRICE_ORDER_LEAD, sum(VAL_ORDER) OVER (order by PRICE_ORDER desc) SUM_VAL from
(select PRICE_ORDER, SUM(VAL_ORDER) VAL_ORDER  from ORDERS where OPER=1 group by PRICE_ORDER)) PR1
where PR.PRICE_ORDER=PR1.PRICE_ORDER or (PR.PRICE_ORDER>PR1.PRICE_ORDER_LEAD and PR.PRICE_ORDER<PR1.PRICE_ORDER)
) as SUM_VAL1,
(select MAX(PR2.SUM_VAL) from 
(select PRICE_ORDER, NVL(LEAD(PRICE_ORDER) OVER (order by PRICE_ORDER asc), 10000000) PRICE_ORDER_LEAD, sum(VAL_ORDER) OVER (order by PRICE_ORDER asc) SUM_VAL from
(select PRICE_ORDER, SUM(VAL_ORDER) VAL_ORDER  from ORDERS where OPER=2 group by PRICE_ORDER)) PR2
where PR.PRICE_ORDER=PR2.PRICE_ORDER or (PR.PRICE_ORDER<PR2.PRICE_ORDER_LEAD and PR.PRICE_ORDER>PR2.PRICE_ORDER)
) as SUM_VAL2
from
(select distinct PRICE_ORDER from ORDERS) PR
order by PR.PRICE_ORDER


Результат запроса
PRICE_ORDER SUM_VAL1 SUM_VAL2
10 18 1
20 18 1
30 13 6
40 13 8
50 13 13
60 13 19
70 9 21
80 5 21
100 3 21

В данном случае равновесная цена 50, а объем 13.
...
Рейтинг: 0 / 0
Задача нахождения равновесной цены спроса и предложения
    #39946141
Фотография Кобанчег
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Energomarket
В данном случае равновесная цена 50, а объем 13.
Какая интересная экономическая реальность.
Объем оказался меньше и объема покупки и объема продажи.
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
select *
  from orders o
 pivot (
  sum(val_order) cnt,
  sum(val_order * price_order) amount
  for oper in (1 buy, 2 sell));

   BUY_CNT BUY_AMOUNT   SELL_CNT SELL_AMOUNT
---------- ---------- ---------- -----------
        18       1080         21         990
...
Рейтинг: 0 / 0
Задача нахождения равновесной цены спроса и предложения
    #39946146
Фотография Кобанчег
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Energomarket,

Для каждого из трех случаев распиши вычисления для ожидаемого ответа
Код: plsql
1.
2.
3.
select 100 as price_order, 10 as val_order, 1 oper from dual union all
select  10 as price_order, 10 as val_order, 1 oper from dual union all
select   5 as price_order, 10 as val_order, 2 oper from dual


Код: plsql
1.
2.
3.
select 100 as price_order, 10 as val_order, 1 oper from dual union all
select  10 as price_order, 10 as val_order, 2 oper from dual union all
select   5 as price_order, 10 as val_order, 2 oper from dual


Код: plsql
1.
2.
3.
select 100 as price_order, 20 as val_order, 1 oper from dual union all
select 100 as price_order, 10 as val_order, 2 oper from dual union all
select  10 as price_order, 10 as val_order, 2 oper from dual
...
Рейтинг: 0 / 0
Задача нахождения равновесной цены спроса и предложения
    #39946179
Energomarket
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Кобанчег,

Ну да равновесная цена обычно на меньшем объеме (все конечно зависит от входных данных)

https://ru.wikipedia.org/wiki/Закон_спроса_и_предложения#/media/Файл:Supply-demand-equilibrium.svg
...
Рейтинг: 0 / 0
Задача нахождения равновесной цены спроса и предложения
    #39946208
Фотография Кобанчег
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Energomarket,

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
select price_order,
       sum(sum(decode(oper, 1, val_order))) over(order by price_order desc) sum_val1,
       sum(sum(decode(oper, 2, val_order))) over(order by price_order) sum_val2
  from orders o
 group by price_order
 order by 1;

PRICE_ORDER   SUM_VAL1   SUM_VAL2
----------- ---------- ----------
         10         18          1
         20         18          1
         30         13          6
         40         13          8
         50         13         13
         60         13         19
         70          9         21
         80          5         21
        100          3         21

9 rows selected.

nvl дописывать лень
...
Рейтинг: 0 / 0
Задача нахождения равновесной цены спроса и предложения
    #39946214
Energomarket
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Кобанчег,

1) Для случая
select 100 as price_order, 10 as val_order, 1 oper from dual union all
select 10 as price_order, 10 as val_order, 1 oper from dual union all
select 5 as price_order, 10 as val_order, 2 oper from dual

Результат:
Цена Объем покупки Объем продажи
5 20 10
10 20 10
100 10 10

За цену 5 и 10 все покупатели готовы преобрести товар. Точка пересечения - цена 100 объем 10.
Если разрабатывать биржу то итоговая цена будет 10, и объем 10. Но купит товар покупатель с ценой 100 (точка пересечения).

2) Для случая
select 100 as price_order, 10 as val_order, 1 oper from dual union all
select 10 as price_order, 10 as val_order, 2 oper from dual union all
select 5 as price_order, 10 as val_order, 2 oper from dual

Результат:
Цена Объем покупки Объем продажи
5 10 10
10 10 20
100 10 20
За цену 5, 10 и 100 все покупатели (в данном случае 1) готовы преобрести товар. Точка пересечения - цена 5 объем 10.
Для биржи тоже цена 5 объем 10.

3) Для случая
select 100 as price_order, 20 as val_order, 1 oper from dual union all
select 100 as price_order, 10 as val_order, 2 oper from dual union all
select 10 as price_order, 10 as val_order, 2 oper from dual

Результат:
Цена Объем покупки Объем продажи
10 20 10
100 20 20

За цену 10 и 100 все покупатели готовы преобрести товар. Точка пересечения - цена 100 объем 20.
Для биржи тоже цена 100 объем 20.
...
Рейтинг: 0 / 0
Задача нахождения равновесной цены спроса и предложения
    #39946215
Energomarket
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Кобанчег
Energomarket,

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
select price_order,
       sum(sum(decode(oper, 1, val_order))) over(order by price_order desc) sum_val1,
       sum(sum(decode(oper, 2, val_order))) over(order by price_order) sum_val2
  from orders o
 group by price_order
 order by 1;

PRICE_ORDER   SUM_VAL1   SUM_VAL2
----------- ---------- ----------
         10         18          1
         20         18          1
         30         13          6
         40         13          8
         50         13         13
         60         13         19
         70          9         21
         80          5         21
        100          3         21

9 rows selected.

nvl дописывать лень

Спасибо. Производительность этого запроса в моих примерах выше раза в три.
...
Рейтинг: 0 / 0
Задача нахождения равновесной цены спроса и предложения
    #39946219
Фотография Кобанчег
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Energomarket,

Если интересует апроксимация:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
select min(price_order) +
       nvl((max(buy_amount) - min(sell_amount)) /
           nullif((max(buy_amount) - min(sell_amount) + max(sell_amount) - min(buy_amount)), 0) *
           (max(price_order) - min(price_order)), 0) market_price
  from (select t.*
               , row_number() over (order by case when buy_amount >= sell_amount then buy_amount end, price_order desc) rn1
               , row_number() over (order by case when buy_amount <= sell_amount then sell_amount end, price_order asc) rn2
          from (select price_order,
                       sum(sum(decode(oper, 1, val_order))) over(order by price_order desc) buy_amount,
                       sum(sum(decode(oper, 2, val_order))) over(order by price_order) sell_amount
                  from orders o
                 group by price_order) t)
 where 1 in (rn1, rn2)
 order by price_order;
...
Рейтинг: 0 / 0
Задача нахождения равновесной цены спроса и предложения
    #39946221
Правильный Вася
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Думаю что запрос построен не оптимальным способом (время его отработки при больших объемах заявок и циклических вызовах будет слишком большим)
Что есть циклический вызов в вашем контексте?
И как часто вы собираетесь проводить такую аналитику? Надеюсь, не каждый час?

Просто бывают вещи, которые просто нужно сделать, не обязательно идеально.
...
Рейтинг: 0 / 0
Задача нахождения равновесной цены спроса и предложения
    #39946237
Energomarket
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Кобанчег
Energomarket,

Если интересует апроксимация:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
select min(price_order) +
       nvl((max(buy_amount) - min(sell_amount)) /
           nullif((max(buy_amount) - min(sell_amount) + max(sell_amount) - min(buy_amount)), 0) *
           (max(price_order) - min(price_order)), 0) market_price
  from (select t.*
               , row_number() over (order by case when buy_amount >= sell_amount then buy_amount end, price_order desc) rn1
               , row_number() over (order by case when buy_amount <= sell_amount then sell_amount end, price_order asc) rn2
          from (select price_order,
                       sum(sum(decode(oper, 1, val_order))) over(order by price_order desc) buy_amount,
                       sum(sum(decode(oper, 2, val_order))) over(order by price_order) sell_amount
                  from orders o
                 group by price_order) t)
 where 1 in (rn1, rn2)
 order by price_order;



За апроксимацию отдельное спасибо. Вы как будто этим вопросом раньше занимались.
...
Рейтинг: 0 / 0
Задача нахождения равновесной цены спроса и предложения
    #39946244
Energomarket
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Правильный Вася
Думаю что запрос построен не оптимальным способом (время его отработки при больших объемах заявок и циклических вызовах будет слишком большим)

Что есть циклический вызов в вашем контексте?
И как часто вы собираетесь проводить такую аналитику? Надеюсь, не каждый час?

Просто бывают вещи, которые просто нужно сделать, не обязательно идеально.
Есть биржи, которые предоставляют своим клиентам интересные варианты заявок на покупку/продажу товара.
Иногда найти пересечение спроса и предложения недостаточно и нужно перебрать несколько вариантов таких пересечений.
Это делается для поиска наибольшего зароботка для покупателей и продавцов на бирже.
И в таком случае поиск пересечение спроса и предложения должен работать максимально быстро.
Ваш вариант работает оптимально быстро.
Такими ответами вы спасаете мир.
...
Рейтинг: 0 / 0
Задача нахождения равновесной цены спроса и предложения
    #39946246
Energomarket
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Правильный Вася
Думаю что запрос построен не оптимальным способом (время его отработки при больших объемах заявок и циклических вызовах будет слишком большим)

Что есть циклический вызов в вашем контексте?
И как часто вы собираетесь проводить такую аналитику? Надеюсь, не каждый час?

Просто бывают вещи, которые просто нужно сделать, не обязательно идеально.
Сейчас вызовов порядка 1000 в сутки. Но будем пробовать до 1 000 0000.
...
Рейтинг: 0 / 0
Задача нахождения равновесной цены спроса и предложения
    #39946248
Фотография Кобанчег
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Energomarket
Сейчас вызовов порядка 1000 в сутки. Но будем пробовать до 1 000 0000.
1000 вызовов в сутки это в среднем менее вызова в минуту - проблем может и не быть если объемы данных не миллионы строк.
А в случае 1 000 000 вызовов SQL решение вообще вариант. Массив данных и pre-calculated values надо держать в памяти.
Приведенное SQL решение можно слегка оптимизировать так что вместо 4-х операций WINDOW SORT/WINDOW BUFFER будет одна, но это особой погоды не сделает.
...
Рейтинг: 0 / 0
Задача нахождения равновесной цены спроса и предложения
    #39946271
Energomarket
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Кобанчег
Energomarket
Сейчас вызовов порядка 1000 в сутки. Но будем пробовать до 1 000 0000.
1000 вызовов в сутки это в среднем менее вызова в минуту - проблем может и не быть если объемы данных не миллионы строк.
А в случае 1 000 000 вызовов SQL решение вообще вариант. Массив данных и pre-calculated values надо держать в памяти.
Приведенное SQL решение можно слегка оптимизировать так что вместо 4-х операций WINDOW SORT/WINDOW BUFFER будет одна, но это особой погоды не сделает.

На данном этапе sql полностью устаивает, так как не требует переработки всего кода.
В будущем планируем рабтать с массивами, но нужно код переписывать.
Возможно рассмотрим внешние модули к oracle (язык более низкого уровня), на массивы plsql меньше надежды.
...
Рейтинг: 0 / 0
14 сообщений из 14, страница 1 из 1
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Задача нахождения равновесной цены спроса и предложения
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]