Spaces:
Sleeping
Sleeping
Update valuation
Browse files
valuation
CHANGED
|
@@ -66,3 +66,71 @@ def deal_score(predicted_resale: float, ask: float, fee_rate: float=0.13, ship:
|
|
| 66 |
elif profit >= 5: label = "Meh"
|
| 67 |
else: label = "Pass"
|
| 68 |
return round(fees,2), round(net,2), round(profit,2), round(margin,2), label
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 66 |
elif profit >= 5: label = "Meh"
|
| 67 |
else: label = "Pass"
|
| 68 |
return round(fees,2), round(net,2), round(profit,2), round(margin,2), label
|
| 69 |
+
import pandas as pd
|
| 70 |
+
from sklearn.feature_extraction.text import TfidfVectorizer
|
| 71 |
+
from sklearn.pipeline import Pipeline
|
| 72 |
+
from sklearn.compose import ColumnTransformer
|
| 73 |
+
from sklearn.preprocessing import OneHotEncoder
|
| 74 |
+
from sklearn.linear_model import Ridge
|
| 75 |
+
|
| 76 |
+
# Tiny seed comps to learn rough resale from titles/brands
|
| 77 |
+
SEED = [
|
| 78 |
+
("Nintendo Wii Console with controllers","Electronics","Nintendo","Used-Good",85),
|
| 79 |
+
("Vintage Pyrex mixing bowl set","Home & Kitchen","Pyrex","Used-Good",120),
|
| 80 |
+
("Levi's 501 jeans men's 34x32","Clothing","Levi's","Used-Good",28),
|
| 81 |
+
("Patagonia Synchilla fleece pullover M","Clothing","Patagonia","Used-Good",45),
|
| 82 |
+
("KitchenAid Artisan stand mixer","Home & Kitchen","KitchenAid","Used-Good",220),
|
| 83 |
+
("Bose QuietComfort 35 headphones","Electronics","Bose","Used-Good",140),
|
| 84 |
+
("Apple iPhone 11 128GB unlocked","Electronics","Apple","Used-Good",240),
|
| 85 |
+
("Herman Miller Aeron chair size B","Furniture","Herman Miller","Used-Good",500),
|
| 86 |
+
("Sony PlayStation 2 console slim","Electronics","Sony","Used-Good",75),
|
| 87 |
+
("Le Creuset dutch oven 5.5 qt","Home & Kitchen","Le Creuset","Used-Good",240),
|
| 88 |
+
("Sony Walkman cassette player","Electronics","Sony","Used-Good",95),
|
| 89 |
+
("All-Clad stainless pan 10 inch","Home & Kitchen","All-Clad","Used-Good",55),
|
| 90 |
+
("Coach leather handbag crossbody","Accessories","Coach","Used-Good",65),
|
| 91 |
+
("Seiko 5 automatic watch SNK809","Accessories","Seiko","Used-Good",95),
|
| 92 |
+
]
|
| 93 |
+
|
| 94 |
+
def _seed_df():
|
| 95 |
+
return pd.DataFrame(SEED, columns=["title","category","brand","condition","price"])
|
| 96 |
+
|
| 97 |
+
class DealValuator:
|
| 98 |
+
def __init__(self, df: pd.DataFrame | None = None):
|
| 99 |
+
self.df = df if df is not None else _seed_df()
|
| 100 |
+
self.model = self._train(self.df)
|
| 101 |
+
|
| 102 |
+
def _train(self, df: pd.DataFrame):
|
| 103 |
+
text_features = 'title'
|
| 104 |
+
cat_features = ['category','brand','condition']
|
| 105 |
+
pre = ColumnTransformer([
|
| 106 |
+
('t', TfidfVectorizer(ngram_range=(1,2), min_df=1), text_features),
|
| 107 |
+
('c', OneHotEncoder(handle_unknown='ignore'), cat_features),
|
| 108 |
+
])
|
| 109 |
+
model = Pipeline([('pre', pre), ('reg', Ridge(alpha=1.0))])
|
| 110 |
+
X = df[['title','category','brand','condition']]
|
| 111 |
+
y = df['price']
|
| 112 |
+
model.fit(X, y)
|
| 113 |
+
return model
|
| 114 |
+
|
| 115 |
+
def predict_resale(self, title: str, category: str | None = None,
|
| 116 |
+
brand: str | None = None, condition: str = 'Used-Good') -> float:
|
| 117 |
+
X = pd.DataFrame([{
|
| 118 |
+
'title': title or '',
|
| 119 |
+
'category': category or 'Unknown',
|
| 120 |
+
'brand': brand or 'Unknown',
|
| 121 |
+
'condition': condition or 'Used-Good'
|
| 122 |
+
}])
|
| 123 |
+
pred = float(self.model.predict(X)[0])
|
| 124 |
+
return max(5.0, round(pred, 2))
|
| 125 |
+
|
| 126 |
+
def deal_score(predicted_resale: float, ask: float, fee_rate: float = 0.13, ship: float = 12.0):
|
| 127 |
+
fees = predicted_resale * fee_rate
|
| 128 |
+
net = predicted_resale - fees - ship
|
| 129 |
+
profit = net - ask
|
| 130 |
+
margin = (profit / ask) if ask > 0 else 0.0
|
| 131 |
+
if profit >= 50 and margin >= 0.8: label = "Home Run"
|
| 132 |
+
elif profit >= 25 and margin >= 0.5: label = "Great"
|
| 133 |
+
elif profit >= 10 and margin >= 0.3: label = "Good"
|
| 134 |
+
elif profit >= 5: label = "Meh"
|
| 135 |
+
else: label = "Pass"
|
| 136 |
+
return round(fees,2), round(net,2), round(profit,2), round(margin,2), label
|