Получение прибыли за первый месяц в таблице SQL, содержащей данные по валютным сделкам - PullRequest
0 голосов
/ 28 апреля 2020

У меня есть таблица Oracle SQL, которая содержит всю торговую информацию по FX, связанную с сделками, совершенными клиентами. Запись создается для начальной сделки открытия, а затем создается другая запись, когда эта сделка закрывается Вторая запись содержит информацию о прибыли / убытке по этой сделке. Идентификатор начальной сделки также фиксируется во второй записи как 'initial_trade_id' (или заполняется 0, если запись предназначена для начальной сделки)

Что я хотел бы - это рассчитать долю клиентов, которые сделали успешных прибыльных сделок в течение месяца после их первой сделки. Я только хочу рассмотреть сделки, которые были закрыты, и забыть активные. Окончательный результат должен отвечать этому утверждению: «Из числа клиентов, которые торговали в течение месяца с момента первой сделки, число X в целом было прибыльным, а число Y - убыточным в целом»

Схема таблицы такая (игнорируя нерегулярные столбцы):

+--------------------------+
| TRADE_ID                 | 
| TRADE_TIMESTAMP          | => 'DD-MON-YY HH-MM-SS'
| CLIENT_ID                | 
| INITIAL_TRADE_ID         | => is 0 if entry is the initial trade or 'TRADE_ID' if closing trade
| TRADE_PROFIT_LOSS_AMOUNT | => can be positive or negative
+--------------------------+

Примером пары записей будет

+-------+----------------------+-----+-------+-----+
| ZXCVB | 12-JAN-2020 08.00.00 | 123 | ASDFG | 159 |
+-------+----------------------+-----+-------+-----+
| ASDFG | 01-JAN-2020 14.00.00 | 123 |     0 |   0 |
+-------+----------------------+-----+-------+-----+

. Сначала я думал об этом, чтобы использовать ROWNUM для получения первой сделки для каждого клиента, а затем искать закрытие. сделки, которые находятся в пределах месяца с этой первой торговой даты, перед тем как получить СРЕДНЕЕ на каждого клиента, затем использовать SUM и CASE на основе положительного / отрицательного значения avg для получения доли успешных сделок. Однако у меня возникли проблемы с обработкой этого запроса, поэтому любая помощь будет оценена.

В конце я бы хотел получить:

+----------------------------+--------------------------+
| PROFIT_MAKING_CLIENT_COUNT | LOSS_MAKING_CLIENT_COUNT |
+----------------------------+--------------------------+
|                        924 |                      459 |
+----------------------------+--------------------------+

, т. Е. Если через месяц Среднее значение клиента TRADE_PROFIT_LOSS_AMOUNT является положительным на основе всех их закрытых сделок, к PROFIT_MAKING_CLIENT_COUNT (и наоборот) добавляется число, равное одному

Ответы [ 2 ]

0 голосов
/ 28 апреля 2020

Когда возникает такая проблема, первое, что нужно сделать, это разбить ее на отдельные элементы. Ваше заявление о проблеме:

Из числа клиентов, которые торговали в течение месяца с момента первой сделки, число Х было прибыльным> в целом, а число Y - убыточным в целом

Чтобы получить список клиентов, торгующих не менее одного месяца, вы можете использовать:

SELECT CLIENT_ID,
       MONTHS_BETWEEN(SYSDATE, MIN(TRADE_TIMESTAMP)) AS TRADING_MONTHS
  FROM YOUR_TABLE
  GROUP BY CLIENT_ID
  HAVING MONTHS_BETWEEN(SYSDATE, MIN(TRADE_TIMESTAMP)) >= 1

Далее необходимо суммировать прибыль и убытки клиентов:

SELECT CLIENT_ID
       SUM(TRADE_PROFIT_LOSS_AMOUNT) AS TOTAL_PROFIT_LOSS
  FROM YOUR_TABLE
  GROUP BY CLIENT_ID

Затем выведите клиентов, которые зарабатывают и теряют деньги, следующим образом:

SELECT CLIENT_ID
  FROM cteClient_profit_loss
  WHERE TOTAL_PROFIT_LOSS > 0

и

SELECT CLIENT_ID
  FROM cteClient_profit_loss
  WHERE TOTAL_PROFIT_LOSS < 0

Затем просто посчитайте результаты каждого подзапроса и соберите все вместе, и вы получите :

WITH cteActive_clients AS
       (SELECT CLIENT_ID,
               MONTHS_BETWEEN(SYSDATE, MIN(TRADE_TIMESTAMP)) AS TRADING_MONTHS
          FROM YOUR_TABLE
          GROUP BY CLIENT_ID
          HAVING MONTHS_BETWEEN(SYSDATE, MIN(TRADE_TIMESTAMP)) >= 1),
     cteActive_client_count AS
       (SELECT COUNT(*) AS ACTIVE_CLIENT_COUNT
          FROM cteActive_clients),
     cteClient_profit_loss AS
       (SELECT CLIENT_ID
               SUM(TRADE_PROFIT_LOSS_AMOUNT) AS TOTAL_PROFIT_LOSS
          FROM YOUR_TABLE
          GROUP BY CLIENT_ID),
     cteClients_profitable AS
       (SELECT CLIENT_ID
          FROM cteClient_profit_loss
          WHERE TOTAL_PROFIT_LOSS > 0),
     cteProfitable_client_count AS
       (SELECT COUNT(*) AS PROFITABLE_CLIENT_COUNT
          FROM cteClients_profitable),
     cteClients_losing_money AS
       (SELECT CLIENT_ID
          FROM cteClient_profit_loss
          WHERE TOTAL_PROFIT_LOSS < 0),
     cteMoney_losing_client_count AS
       (SELECT COUNT(*) AS MONEY_LOSING_CLIENT_COUNT
          FROM cteClients_losing_money)
SELECT PROFITABLE_CLIENT_COUNT,
       MONEY_LOSING_CLIENT_COUNT
  FROM cteProfitable_client_count
  CROSS JOIN cteMoney_losing_client_count
0 голосов
/ 28 апреля 2020

Вы можете получить первую сделку, а затем агрегировать. Я не уверен, каково точное определение флагов, но, похоже, вам нужна эта информация:

select client_id,
       sum(TRADE_PROFIT_LOSS_AMOUNT) as profit_30_days,
       max(TRADE_PROFIT_LOSS_AMOUNT) as any_profit_30_days
from (select t.*, min(trade_timestamp) over (partition by client_id) as min_tt
      from t
     ) t
where trade_timestamp < min_tt + interval '30' day
group by client_id;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...