File size: 4,765 Bytes
c7e1bab
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
import gradio as gr
import pandas as pd
from sklearn.preprocessing import PolynomialFeatures
from pymongo import MongoClient
import pickle
import joblib

# --- MongoDB Setup ---
uri = "mongodb+srv://csmith715:I3xSO3ImRKFyQ0hf@cluster0.hc5mw.mongodb.net/"
client = MongoClient(uri)
database = client.get_database("gemrate")
market_data = database.get_collection("alt_market_data")

# --- Load Model and Encoder ---
gradient_boosting_reg = joblib.load('gbm_card_model.joblib')
with open('card_encoder.pkl', 'rb') as file:
    loaded_encoder = pickle.load(file)


# --- Helper Functions ---
def transform_data(dframe):
    dframe = pd.get_dummies(dframe, columns=['grader'])
    dframe['ds'] = pd.to_datetime(dframe['ds'])
    dframe['year'] = dframe['ds'].dt.year
    dframe['month'] = dframe['ds'].dt.month
    dframe['day_of_week'] = dframe['ds'].dt.dayofweek
    dframe = dframe.drop('ds', axis=1)
    dframe['grade'] = pd.to_numeric(dframe['grade'], errors='coerce')
    poly = PolynomialFeatures(degree=3, include_bias=False)
    grade_poly = poly.fit_transform(dframe[['grade']])
    grade_poly_df = pd.DataFrame(grade_poly, columns=['grade1', 'grade^2', 'grade^3'])
    dframe = pd.concat([dframe, grade_poly_df], axis=1)
    dframe = dframe.drop('grade1', axis=1)
    return dframe


def calculate_moving_averages(dframe):
    dframe['ds'] = pd.to_datetime(dframe['ds'])
    dframe['y'] = dframe['y'].astype(float)
    dframe = dframe.sort_values(by=['certnumber', 'grade', 'grader', 'ds'])
    dframe.set_index('ds', inplace=True)

    def compute_group_moving_averages(group):
        group = group.sort_index()
        group['ma_3d'] = group['y'].rolling('3D').mean()
        group['ma_7d'] = group['y'].rolling('7D').mean()
        group['ma_30d'] = group['y'].rolling('30D').mean()
        return group

    grouped = dframe.groupby(['certnumber', 'grade', 'grader'], group_keys=False)
    dframe = grouped.apply(compute_group_moving_averages)
    return dframe.reset_index()


def lookup_certnumber(certnumber):
    results = market_data.find(
        {'cert_number': certnumber},
        {
            '_id': 0,
            'market_transaction.date': 1,
            'market_transaction.price': 1,
            'market_transaction.attributes.gradeNumber': 1,
            'market_transaction.attributes.gradingCompany': 1
        }
    )
    data = []
    for r in results:
        tx = r.get('market_transaction', {})
        attributes = tx.get('attributes', {})
        data.append({
            'ds': tx.get('date'),
            'y': tx.get('price'),
            'grade': attributes.get('gradeNumber'),
            'grader': attributes.get('gradingCompany')
        })

    df = pd.DataFrame(data)
    df['certnumber'] = [certnumber] * df.shape[0]
    return df


# --- Prediction Logic ---
def predict_price(certnumber, grader, grade):
    cert_df = lookup_certnumber(certnumber)
    if cert_df.empty:
        return "No data found for this cert number.", pd.DataFrame()

    cert_df = cert_df[(cert_df['grader'] == grader) & (cert_df['grade'] == grade)]
    if cert_df.empty:
        return "No matching data found for this grader and grade.", pd.DataFrame()

    moving_average_df = calculate_moving_averages(cert_df)
    moving_average_df['certnumber'] = moving_average_df['certnumber'].astype(str)

    # Encode certnumber
    moving_average_df['certnumber_encoded'] = loaded_encoder.fit_transform(
        moving_average_df['certnumber'], moving_average_df['y'])

    filtered_cert_df = moving_average_df.drop(['y', 'certnumber'], axis=1)
    max_fdate = filtered_cert_df['ds'].max()
    filtered_df = filtered_cert_df[filtered_cert_df['ds'] == max_fdate]

    tdf = transform_data(filtered_df).fillna(0)
    tdf = tdf[tdf.grade != 0]

    model_columns = gradient_boosting_reg.feature_names_in_
    for col in model_columns:
        if col not in tdf.columns:
            tdf[col] = [0]*tdf.shape[0]

    tdf = tdf[model_columns]
    predictions = gradient_boosting_reg.predict(tdf)

    tdf['Predicted Price'] = predictions
    return f"Predicted Price: ${predictions[0]:,.2f}", tdf


# --- Gradio UI ---
with gr.Blocks() as demo:
    gr.Markdown("# Pokémon Card Price Predictor")

    cert_input = gr.Number(label="Cert Number", precision=0)
    grader_input = gr.Dropdown(choices=["PSA", "BGS", "CGC"], label="Grader")
    grade_input = gr.Textbox(label="Grade (e.g., 10.0)")

    submit_btn = gr.Button("Predict Price")
    output_text = gr.Textbox(label="Prediction Result")
    output_df = gr.Dataframe(label="Transformed Input Features")

    submit_btn.click(
        predict_price,
        inputs=[cert_input, grader_input, grade_input],
        outputs=[output_text, output_df]
    )

demo.launch(auth=("pokecards", "exqeQbBHrKVL"))