Гость
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Задача нахождения равновесной цены спроса и предложения / 14 сообщений из 14, страница 1 из 1
11.04.2020, 10:14
    #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
11.04.2020, 13:14
    #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
11.04.2020, 13:24
    #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
11.04.2020, 16:36
    #39946179
Energomarket
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Задача нахождения равновесной цены спроса и предложения
Кобанчег,

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

https://ru.wikipedia.org/wiki/Закон_спроса_и_предложения#/media/Файл:Supply-demand-equilibrium.svg
...
Рейтинг: 0 / 0
11.04.2020, 18:34
    #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
11.04.2020, 19:32
    #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
11.04.2020, 19:40
    #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
11.04.2020, 19:53
    #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
11.04.2020, 20:00
    #39946221
Правильный Вася
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Задача нахождения равновесной цены спроса и предложения
Думаю что запрос построен не оптимальным способом (время его отработки при больших объемах заявок и циклических вызовах будет слишком большим)
Что есть циклический вызов в вашем контексте?
И как часто вы собираетесь проводить такую аналитику? Надеюсь, не каждый час?

Просто бывают вещи, которые просто нужно сделать, не обязательно идеально.
...
Рейтинг: 0 / 0
11.04.2020, 20:59
    #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
11.04.2020, 21:06
    #39946244
Energomarket
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Задача нахождения равновесной цены спроса и предложения
Правильный Вася
Думаю что запрос построен не оптимальным способом (время его отработки при больших объемах заявок и циклических вызовах будет слишком большим)

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

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

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

Просто бывают вещи, которые просто нужно сделать, не обязательно идеально.
Сейчас вызовов порядка 1000 в сутки. Но будем пробовать до 1 000 0000.
...
Рейтинг: 0 / 0
11.04.2020, 21:26
    #39946248
Кобанчег
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Задача нахождения равновесной цены спроса и предложения
Energomarket
Сейчас вызовов порядка 1000 в сутки. Но будем пробовать до 1 000 0000.
1000 вызовов в сутки это в среднем менее вызова в минуту - проблем может и не быть если объемы данных не миллионы строк.
А в случае 1 000 000 вызовов SQL решение вообще вариант. Массив данных и pre-calculated values надо держать в памяти.
Приведенное SQL решение можно слегка оптимизировать так что вместо 4-х операций WINDOW SORT/WINDOW BUFFER будет одна, но это особой погоды не сделает.
...
Рейтинг: 0 / 0
11.04.2020, 23:45
    #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
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Задача нахождения равновесной цены спроса и предложения / 14 сообщений из 14, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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