generated from user_client2024/58
169 lines
5.1 KiB
Python
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[ ]:
|
|
|
|
|
|
|
|
|