61/main.py
2024-10-15 11:39:00 +00:00

169 lines
5.1 KiB
Python

#!/usr/bin/env python
# coding: utf-8
# In[12]:
from datetime import datetime
import pandas as pd
from tms_data_interface import SQLQueryInterface
query = """
WITH
-- Capture all orders and trades within the spoofing time window
trade_window AS (
SELECT
t.trade_id,
t.trader_id,
t.date_time AS trade_time,
t.trade_side,
t.trade_volume,
o.trader_id AS order_trader_id,
o.date_time AS order_time,
o.order_volume,
o.order_status,
o.order_price,
o.side AS order_side
FROM
{trade_10m_v3} t
LEFT JOIN
order_10m o ON o.date_time BETWEEN t.date_time - INTERVAL '{spoofing_time_window_s}' SECOND
AND t.date_time
WHERE
o.side = '{spoofing_side}'
),
-- Calculate net order volume for the specific trader
net_order_volume_cte AS (
SELECT
trader_id,
trade_id,
trade_time,
SUM(CASE
WHEN order_status = 'new' THEN order_volume
WHEN order_status = 'cancelled' THEN -order_volume
WHEN order_status = 'fulfilled' THEN -order_volume
ELSE 0
END) AS net_order_volume,
COUNT(*) AS num_orders
FROM trade_window
WHERE order_trader_id = trader_id -- Filter by the trader who executed the trade
GROUP BY trader_id, trade_id, trade_time
),
-- Calculate total net order volume for all traders (i.e., for spoofing side orders)
net_order_volume_all_cte AS (
SELECT
trade_id,
SUM(CASE
WHEN order_status = 'new' THEN order_volume
WHEN order_status = 'cancelled' THEN -order_volume
WHEN order_status = 'fulfilled' THEN -order_volume
ELSE 0
END) AS net_order_volume_all
FROM trade_window
GROUP BY trade_id
),
-- Calculate total trade volume on the opposite side (e.g., sell if spoofing is on buy)
opposite_trade_volume_cte AS (
SELECT
t.trader_id,
t.trade_id,
SUM(t.trade_volume) AS total_trade_volume
FROM {trade_10m_v3} t
WHERE
t.date_time BETWEEN t.date_time - INTERVAL '{trade_time_window_s}' SECOND
AND t.date_time
AND t.trade_side = CASE WHEN '{spoofing_side}' = 'buy' THEN 'sell' ELSE 'buy' END
GROUP BY t.trader_id, t.trade_id
)
-- Final result with calculated spoofing indicators
SELECT
n.trade_id,
n.trader_id,
n.trade_time,
n.num_orders,
n.net_order_volume,
CASE
WHEN o.total_trade_volume > 0 THEN n.net_order_volume / o.total_trade_volume
ELSE NULL
END AS order_trade_ratio,
CASE
WHEN a.net_order_volume_all > 0 THEN n.net_order_volume / a.net_order_volume_all
ELSE NULL
END AS volume_percentage
FROM
net_order_volume_cte n
LEFT JOIN
opposite_trade_volume_cte o ON n.trade_id = o.trade_id
LEFT JOIN
net_order_volume_all_cte a ON n.trade_id = a.trade_id
WHERE
n.net_order_volume > 0 -- Only consider positive net order volumes (potential spoofing);
limit 100
"""
class Scenario:
seq = SQLQueryInterface(schema="trade_schema")
def logic(self, **params):
spoofing_time_window = params.get('spoofing_time_window', 300000) # default to 300,000 ms (5 minutes)
spoofing_side = params.get('spoofing_side', 'buy')
use_volume_for_order_trade_ratio = params.get('use_volume_for_order_trade_ratio', True)
trade_time_window = params.get('trade_time_window', 300000)
ignore_trade_after_spoofing = params.get('ignore_trade_after_spoofing', True)
ignore_price_improvement = params.get('ignore_price_improvement', True)
# Convert time windows from milliseconds to seconds
spoofing_time_window_s = int(spoofing_time_window / 1000)
trade_time_window_s = int(trade_time_window / 1000)
query_start_time = datetime.now()
print("Query start time:", query_start_time)
# Execute the query with the parameters passed from `params`
row_list = self.seq.execute_raw(query.format(
trade_10m_v3="trade_10m_v3", # Replace with actual table name
spoofing_time_window_s=spoofing_time_window_s,
trade_time_window_s=trade_time_window_s,
spoofing_side=spoofing_side
))
# Define columns for the resulting DataFrame
cols = [
'trade_id', 'focal_id', 'trade_time', 'num_orders',
'net_order_volume', 'order_trade_ratio', 'volume_percentage'
]
# Create a DataFrame from the query result
final_scenario_df = pd.DataFrame(row_list, columns=cols)
# Adding additional columns
final_scenario_df['segment'] = 'Default'
final_scenario_df['sar_flag'] = 'N'
final_scenario_df['risk'] = 'Low Risk'
return final_scenario_df
# In[ ]:
scenario = Scenario()
scenario.logic(spoofing_time_window = 300000,
spoofing_side = 'buy',
use_volume_for_order_trade_ratio = True,
trade_time_window = 300000,
ignore_trade_after_spoofing = True,
ignore_price_improvement = True)
# In[ ]: