mirror of
https://github.com/velocitatem/PHANTOM.git
synced 2026-05-31 08:33:36 +00:00
feat: expanding market observation space
This commit is contained in:
@@ -291,6 +291,7 @@ class CommercePlatform:
|
|||||||
"mean_sale_price": 0.0,
|
"mean_sale_price": 0.0,
|
||||||
"look_to_book": 0.0,
|
"look_to_book": 0.0,
|
||||||
"coi": 0.0,
|
"coi": 0.0,
|
||||||
|
"expected_premium": 0.0,
|
||||||
}
|
}
|
||||||
|
|
||||||
purchases = interaction_df[interaction_df["eventName"] == "purchase_complete"]
|
purchases = interaction_df[interaction_df["eventName"] == "purchase_complete"]
|
||||||
@@ -330,7 +331,7 @@ class CommercePlatform:
|
|||||||
}
|
}
|
||||||
|
|
||||||
def _session_feature_table(self, df: pd.DataFrame) -> pd.DataFrame:
|
def _session_feature_table(self, df: pd.DataFrame) -> pd.DataFrame:
|
||||||
# TODO: adapt this
|
"""Extract per-session behavioral features for separability analysis."""
|
||||||
if df.empty:
|
if df.empty:
|
||||||
return pd.DataFrame()
|
return pd.DataFrame()
|
||||||
g = df.groupby("session_id", sort=False)
|
g = df.groupby("session_id", sort=False)
|
||||||
@@ -341,8 +342,13 @@ class CommercePlatform:
|
|||||||
views = g.apply(lambda x: int((x["eventName"] == "view_item_page").sum()), include_groups=False)
|
views = g.apply(lambda x: int((x["eventName"] == "view_item_page").sum()), include_groups=False)
|
||||||
cart_adds = g.apply(lambda x: int((x["eventName"] == "add_item_to_cart").sum()), include_groups=False)
|
cart_adds = g.apply(lambda x: int((x["eventName"] == "add_item_to_cart").sum()), include_groups=False)
|
||||||
purchases = g.apply(lambda x: int((x["eventName"] == "purchase_complete").sum()), include_groups=False)
|
purchases = g.apply(lambda x: int((x["eventName"] == "purchase_complete").sum()), include_groups=False)
|
||||||
|
learn_more = g.apply(lambda x: int((x["eventName"] == "learn_more_about_item").sum()), include_groups=False)
|
||||||
conversion_rate = purchases / (views + 1e-6)
|
conversion_rate = purchases / (views + 1e-6)
|
||||||
is_agent = g["actor"].apply(lambda s: bool((s == "agent").any()), include_groups=False)
|
is_agent = g["actor"].apply(lambda s: bool((s == "agent").any()), include_groups=False)
|
||||||
|
# price sensitivity features
|
||||||
|
price_variance = g["price_offered"].var().fillna(0.0)
|
||||||
|
avg_price_seen = g["price_offered"].mean().fillna(0.0)
|
||||||
|
products_viewed = g["product_idx"].nunique()
|
||||||
|
|
||||||
return pd.DataFrame({
|
return pd.DataFrame({
|
||||||
"session_duration_sec": session_duration.astype(float),
|
"session_duration_sec": session_duration.astype(float),
|
||||||
@@ -352,7 +358,11 @@ class CommercePlatform:
|
|||||||
"item_views": views.astype(int),
|
"item_views": views.astype(int),
|
||||||
"cart_adds": cart_adds.astype(int),
|
"cart_adds": cart_adds.astype(int),
|
||||||
"purchases": purchases.astype(int),
|
"purchases": purchases.astype(int),
|
||||||
|
"learn_more_clicks": learn_more.astype(int),
|
||||||
"conversion_rate": conversion_rate.astype(float),
|
"conversion_rate": conversion_rate.astype(float),
|
||||||
|
"price_variance": price_variance.astype(float),
|
||||||
|
"avg_price_seen": avg_price_seen.astype(float),
|
||||||
|
"products_viewed": products_viewed.astype(int),
|
||||||
"is_agent": is_agent.astype(bool),
|
"is_agent": is_agent.astype(bool),
|
||||||
}).reset_index()
|
}).reset_index()
|
||||||
|
|
||||||
@@ -371,18 +381,25 @@ class PHANTOMEnv(gym.Env):
|
|||||||
self.action_space = spaces.Box(low=-self.constraints.max_price_adjustment,
|
self.action_space = spaces.Box(low=-self.constraints.max_price_adjustment,
|
||||||
high=self.constraints.max_price_adjustment,
|
high=self.constraints.max_price_adjustment,
|
||||||
shape=(self.constraints.product_catalogue_size,), dtype=np.float32)
|
shape=(self.constraints.product_catalogue_size,), dtype=np.float32)
|
||||||
|
n_products = self.constraints.product_catalogue_size
|
||||||
self.observation_space = spaces.Dict({
|
self.observation_space = spaces.Dict({
|
||||||
"elasticity": spaces.Dict({
|
"elasticity": spaces.Dict({
|
||||||
"price": spaces.Box(
|
"price": spaces.Box(
|
||||||
low=np.full((self.constraints.product_catalogue_size,), self.constraints.system_min_price, dtype=np.float32),
|
low=np.full((n_products,), self.constraints.system_min_price, dtype=np.float32),
|
||||||
high=np.full((self.constraints.product_catalogue_size,), self.constraints.system_max_price, dtype=np.float32),
|
high=np.full((n_products,), self.constraints.system_max_price, dtype=np.float32),
|
||||||
dtype=np.float32),
|
dtype=np.float32),
|
||||||
"demand": spaces.Box(
|
"demand": spaces.Box(
|
||||||
low=np.zeros((self.constraints.product_catalogue_size,), dtype=np.float32),
|
low=np.zeros((n_products,), dtype=np.float32),
|
||||||
high=np.full((self.constraints.product_catalogue_size,), 1e6, dtype=np.float32),
|
high=np.full((n_products,), 1e6, dtype=np.float32),
|
||||||
dtype=np.float32),
|
dtype=np.float32),
|
||||||
})
|
}),
|
||||||
# TODO: define more features that we compute from the interaction data
|
"market": spaces.Dict({
|
||||||
|
"alpha_hat": spaces.Box(low=0.0, high=1.0, shape=(1,), dtype=np.float32), # estimated agent share
|
||||||
|
"revenue_rate": spaces.Box(low=0.0, high=1e6, shape=(1,), dtype=np.float32), # recent revenue
|
||||||
|
"conversion_rate": spaces.Box(low=0.0, high=1.0, shape=(1,), dtype=np.float32),
|
||||||
|
"price_volatility": spaces.Box(low=0.0, high=1.0, shape=(1,), dtype=np.float32),
|
||||||
|
}),
|
||||||
|
"cost": spaces.Box(low=0.0, high=self.constraints.system_max_price, shape=(n_products,), dtype=np.float32),
|
||||||
})
|
})
|
||||||
self.commerce_platform = CommercePlatform(
|
self.commerce_platform = CommercePlatform(
|
||||||
product_catalogue_size=self.constraints.product_catalogue_size,
|
product_catalogue_size=self.constraints.product_catalogue_size,
|
||||||
|
|||||||
Reference in New Issue
Block a user