""" Interactive Reciprocal Tariffs Calculator. Original Source: Yi-Cheng Wu (https://github.com/jrycw/tech/blob/master/posts/clone-reciprocal-tariffs-table/20250403.qmd) """ # ============================================================================= # Imports # ============================================================================= import random import polars as pl from great_tables import GT, google_font, html, loc, style, vals import panel as pn import param from panel.custom import JSComponent # Initialize Panel extension with bootstrap design pn.extension(design="bootstrap", defer_load=True) # ============================================================================= # Constants & Global Variables # ============================================================================= # Color palette DARK_NAVY_BLUE = "#0B162A" # background LIGHT_BLUE = "#B5D3E7" # even row background WHITE = "#FFFFFF" # odd row background YELLOW = "#F6D588" # reciprocal tariffs background GOLD = "#FFF8DE" # logo background # Logo image (first element of the returned tuple) logo = vals.fmt_image("logo.png", height=150)[0] # Base tariffs imposed data TARIFFS_IMPOSED = {'country': ['China', 'European Union', 'Vietnam', 'Taiwan', 'Japan', 'India', 'South Korea', 'Thailand', 'Switzerland', 'Indonesia', 'Malaysia', 'Cambodia', 'United Kingdom', 'South Africa', 'Brazil', 'Bangladesh', 'Singapore', 'Israel', 'Philippines', 'Chile', 'Australia', 'Pakistan', 'Turkey', 'Sri Lanka', 'Colombia', 'Peru', 'Nicaragua', 'Norway', 'Costa Rica', 'Jordan', 'Dominican Republic', 'United Arab Emirates', 'New Zealand', 'Argentina', 'Ecuador', 'Guatemala', 'Honduras', 'Madagascar', 'Myanmar (Burma)', 'Tunisia', 'Kazakhstan', 'Serbia', 'Egypt', 'Saudi Arabia', 'El Salvador', "Côte d'Ivoire", 'Laos', 'Botswana', 'Trinidad and Tobago', 'Morocco', 'Papua New Guinea', 'Malawi', 'Liberia', 'British Virgin Islands', 'Afghanistan', 'Zimbabwe', 'Benin', 'Barbados', 'Monaco', 'Syria', 'Uzbekistan', 'Republic of the Congo', 'Djibouti', 'French Polynesia', 'Cayman Islands', 'Kosovo', 'Curaçao', 'Vanuatu', 'Rwanda', 'Sierra Leone', 'Mongolia', 'San Marino', 'Antigua and Barbuda', 'Bermuda', 'Eswatini', 'Marshall Islands', 'Saint Pierre and Miquelon', 'Saint Kitts and Nevis', 'Turkmenistan', 'Grenada', 'Sudan', 'Turks and Caicos Islands', 'Aruba', 'Montenegro', 'Saint Helena', 'Kyrgyzstan', 'Yemen', 'Saint Vincent and the Grenadines', 'Niger', 'Saint Lucia', 'Nauru', 'Equatorial Guinea', 'Iran', 'Libya', 'Samoa', 'Guinea', 'Timor-Leste', 'Montserrat', 'Chad', 'Mali', 'Algeria', 'Oman', 'Uruguay', 'Bahamas', 'Lesotho', 'Ukraine', 'Bahrain', 'Qatar', 'Mauritius', 'Fiji', 'Iceland', 'Kenya', 'Liechtenstein', 'Guyana', 'Haiti', 'Bosnia and Herzegovina', 'Nigeria', 'Namibia', 'Brunei', 'Bolivia', 'Panama', 'Venezuela', 'North Macedonia', 'Ethiopia', 'Ghana', 'Moldova', 'Angola', 'Democratic Republic of the Congo', 'Jamaica', 'Mozambique', 'Paraguay', 'Zambia', 'Lebanon', 'Tanzania', 'Iraq', 'Georgia', 'Senegal', 'Azerbaijan', 'Cameroon', 'Uganda', 'Albania', 'Armenia', 'Nepal', 'Sint Maarten', 'Falkland Islands', 'Gabon', 'Kuwait', 'Togo', 'Suriname', 'Belize', 'Maldives', 'Tajikistan', 'Cabo Verde', 'Burundi', 'Guadeloupe', 'Bhutan', 'Martinique', 'Tonga', 'Mauritania', 'Dominica', 'Micronesia', 'Gambia', 'French Guiana', 'Christmas Island', 'Andorra', 'Central African Republic', 'Solomon Islands', 'Mayotte', 'Anguilla', 'Cocos (Keeling) Islands', 'Eritrea', 'Cook Islands', 'South Sudan', 'Comoros', 'Kiribati', 'Sao Tome and Principe', 'Norfolk Island', 'Gibraltar', 'Tuvalu', 'British Indian Ocean Territory', 'Tokelau', 'Guinea-Bissau', 'Svalbard and Jan Mayen', 'Heard and McDonald Islands', 'Reunion'], 'tariffs_charged': ['67%', '39%', '90%', '64%', '46%', '52%', '50%', '72%', '61%', '64%', '47%', '97%', '10%', '60%', '10%', '74%', '10%', '33%', '34%', '10%', '10%', '58%', '10%', '88%', '10%', '10%', '36%', '30%', '17%', '40%', '10%', '10%', '20%', '10%', '12%', '10%', '10%', '93%', '88%', '55%', '54%', '74%', '10%', '10%', '10%', '41%', '95%', '74%', '12%', '10%', '15%', '34%', '10%', '10%', '49%', '35%', '10%', '10%', '10%', '81%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '44%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '99%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '15%', '10%', '10%', '10%', '10%', '10%', '59%', '25%', '10%', '61%', '10%', '10%', '10%', '10%', '26%', '10%', '59%', '10%', '10%', '10%', '99%', '10%', '10%', '10%', '80%', '63%', '10%', '10%', '73%', '76%', '10%', '70%', '27%', '42%', '47%', '20%', '10%', '29%', '65%', '10%', '17%', '61%', '63%', '22%', '10%', '31%', '10%', '33%', '10%', '10%', '78%', '10%', '10%', '10%', '22%', '20%', '10%', '10%', '10%', '10%', '82%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '58%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '73%'], 'reciprocal_tariffs': ['34%', '20%', '46%', '32%', '24%', '26%', '25%', '36%', '31%', '32%', '24%', '49%', '10%', '30%', '10%', '37%', '10%', '17%', '17%', '10%', '10%', '29%', '10%', '44%', '10%', '10%', '18%', '15%', '10%', '20%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '47%', '44%', '28%', '27%', '37%', '10%', '10%', '10%', '21%', '48%', '37%', '10%', '10%', '10%', '17%', '10%', '10%', '10%', '18%', '10%', '10%', '10%', '41%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '22%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '50%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '30%', '13%', '10%', '31%', '10%', '10%', '10%', '10%', '13%', '10%', '30%', '10%', '10%', '10%', '50%', '10%', '10%', '10%', '40%', '32%', '10%', '10%', '37%', '38%', '10%', '35%', '14%', '21%', '24%', '10%', '10%', '15%', '33%', '10%', '10%', '31%', '32%', '11%', '10%', '16%', '10%', '17%', '10%', '10%', '39%', '10%', '10%', '10%', '11%', '10%', '10%', '10%', '10%', '10%', '41%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '29%', '10%', '10%', '10%', '10%', '10%', '10%', '10%', '37%']} TARIFFS_NOT_PAUSED=["China"] # ============================================================================= # Helper Functions for Tariffs Calculations # ============================================================================= def scale_tariffs(tariffs=TARIFFS_IMPOSED, factor: float = 2) -> dict: """ Create a new tariffs dictionary where the 'reciprocal_tariffs' are scaled based on the factor applied to the 'tariffs_charged'. The 'tariffs_charged' column remains unchanged. """ new_reciprocal = [] for tariff in tariffs["tariffs_charged"]: # Convert percentage string to integer, scale it, and round to nearest integer. num = int(tariff.strip("%")) scaled_value = round(num / factor) new_reciprocal.append(f"{scaled_value}%") return { "country": tariffs["country"], "tariffs_charged": tariffs["tariffs_charged"], "reciprocal_tariffs": new_reciprocal, } def pause_tariffs(tariffs=TARIFFS_IMPOSED) -> dict: """ Create a new tariffs dictionary where the 'reciprocal_tariffs' are scaled based on the factor applied to the 'tariffs_charged'. The 'tariffs_charged' column remains unchanged. """ new_reciprocal = [] for index, tariff in enumerate(tariffs["reciprocal_tariffs"]): # Convert percentage string to integer, scale it, and round to nearest integer. country = tariffs["country"][index] if country in TARIFFS_NOT_PAUSED: new_reciprocal.append(tariff) else: tariff = "10%" new_reciprocal.append(tariff) return { "country": tariffs["country"], "tariffs_charged": tariffs["tariffs_charged"], "reciprocal_tariffs": new_reciprocal, } def retaliate_china_tariffs(tariffs=TARIFFS_IMPOSED) -> dict: """ Create a new tariffs dictionary where the 'reciprocal_tariffs' are scaled based on the factor applied to the 'tariffs_charged'. The 'tariffs_charged' column remains unchanged. """ new_reciprocal = [] for index, tariff in enumerate(tariffs["reciprocal_tariffs"]): # Convert percentage string to integer, scale it, and round to nearest integer. country = tariffs["country"][index] if country=="China": num = int(tariff.strip("%")) scaled_value = num + 50 new_reciprocal.append(f"{scaled_value}%") else: new_reciprocal.append(tariff) return { "country": tariffs["country"], "tariffs_charged": tariffs["tariffs_charged"], "reciprocal_tariffs": new_reciprocal, } def randomize_tariffs(scale: float = 0.5) -> dict: """ Create a new tariffs dictionary with randomized 'tariffs_charged' values (between 10% and 100%) and corresponding 'reciprocal_tariffs' values computed as the scaled (rounded) half. """ new_charged = [] new_reciprocal = [] for _ in TARIFFS_IMPOSED["country"]: rand_value = random.randint(10, 100) new_charged.append(f"{rand_value}%") reciprocal_value = round(rand_value * scale) new_reciprocal.append(f"{reciprocal_value}%") return { "country": TARIFFS_IMPOSED["country"], "tariffs_charged": new_charged, "reciprocal_tariffs": new_reciprocal, } # ============================================================================= # HTML & Style Helpers # ============================================================================= def change_border_radius( content: str, border_radius: int, background_color1: str, background_color2: str ) -> str: """ Wrap the content with nested divs that have the specified border radius and background colors. """ return f"""
{content}
""" def change_border_radius_expr( cols: pl.Expr, return_dtype: pl.DataType, border_radius: int, background_color1: str, background_color2: str, ) -> pl.Expr: """ Apply the change_border_radius function to each element in a Polars column. """ return cols.map_elements( lambda x: change_border_radius(x, border_radius, background_color1, background_color2), return_dtype=return_dtype, ) # ============================================================================= # Table Creation Function # ============================================================================= def create_tariffs_table(tariffs: dict = TARIFFS_IMPOSED) -> GT: """ Create and style the tariffs table using Polars and Great Tables (GT). The table is styled with alternating row colors and custom fonts. """ # Build the Polars DataFrame with an index (used to alternate row styles) df = ( pl.DataFrame(tariffs) .with_row_index("mod") .with_columns(pl.col("mod").mod(2)) .with_columns(*[pl.lit("").alias(str(i)) for i in range(4)]) .with_columns( # Apply border radius styling for "country" and "tariffs_charged" based on the mod value pl.when(pl.col("mod").eq(0)) .then( change_border_radius_expr( pl.col("country", "tariffs_charged"), pl.String, 5, DARK_NAVY_BLUE, LIGHT_BLUE, ) ) .otherwise( change_border_radius_expr( pl.col("country", "tariffs_charged"), pl.String, 5, DARK_NAVY_BLUE, WHITE, ) ), # Style the "reciprocal_tariffs" column change_border_radius_expr( pl.col("reciprocal_tariffs"), pl.String, 5, DARK_NAVY_BLUE, YELLOW ), ) .select(["0", "country", "1", "tariffs_charged", "2", "reciprocal_tariffs", "3"]) # Add an extra empty row at the end of the table .pipe( lambda df_: pl.concat( [df_, pl.DataFrame({col: "" for col in df_.columns})], how="vertical" ) ) ) # Create a GT table and apply styling options table = ( GT(df) .cols_align("center", columns=["tariffs_charged", "reciprocal_tariffs"]) .cols_label( { "country": html( f"""
{logo}      Reciprocal Tariffs   
Country
""" ), "tariffs_charged": html( """Tariffs Charged
to the U.S.A.
Including Currency Manipulation and Trade Barriers""" ), "reciprocal_tariffs": html("U.S.A. Discounted
Reciprocal Tariffs"), "0": "", "1": "", "2": "", "3": "", } ) .cols_width( { "country": "50%", "0": "3%", "1": "7%", "2": "7%", "3": "3%", "tariffs_charged": "18%", "reciprocal_tariffs": "18%", } ) .tab_style( style=style.fill(color=DARK_NAVY_BLUE), locations=[loc.column_labels(), loc.body()] ) .tab_style(style=style.borders(sides="all", color=DARK_NAVY_BLUE), locations=loc.body()) .tab_style( style=style.text(font=google_font(name="Trajan Pro"), weight="bold", size="xx-large"), locations=loc.body(), ) .tab_style( style=style.text(font=google_font(name="Georgia"), weight="bold", size="large"), locations=loc.column_labels(), ) .tab_style(style=style.text(color=WHITE), locations=loc.column_labels()) .tab_style(style=style.css("text-align: center;"), locations=loc.column_labels()) .tab_options(column_labels_border_bottom_style="hidden") .tab_style(style=style.fill(color=DARK_NAVY_BLUE), locations=loc.body(rows=[-1])) ) return table # ============================================================================= # Panel Widgets and Callbacks # ============================================================================= # Reactive variable for tariffs data tariffs_rx = pn.rx(TARIFFS_IMPOSED, sizing_mode="stretch_width") # Scale slider to control tariff scaling factor discount_factor = pn.widgets.FloatSlider( name="DISCOUNT FACTOR", value=2, step=0.1, start=0.1, end=4.0, sizing_mode="stretch_width", max_width=400 ) @pn.depends(discount_factor, watch=True) def update_scaled_tariffs(discount_factor: float): """ Update the tariffs data based on the scaling factor from the slider. """ tariffs_rx.rx.value = scale_tariffs(tariffs_rx.rx.value, discount_factor) # Button to randomize tariff values randomize_button = pn.widgets.Button(name="RANDOM TARIFFS", width=200, button_type="primary", icon="bow") @pn.depends(randomize_button, watch=True) def update_random_tariffs(_): """ Update the tariffs data with randomized values when the randomize button is clicked. """ tariffs_rx.rx.value = randomize_tariffs(discount_factor.value) # Button to reset tariffs to the original imposed values reset_button = pn.widgets.Button(name="PSEUDO TARIFFS", width=200, button_type="primary") @pn.depends(reset_button, watch=True) def reset_tariffs(_): """ Reset the tariffs data to the original imposed tariffs. """ tariffs_rx.rx.value = TARIFFS_IMPOSED pause_button = pn.widgets.Button(name="PAUSE TARIFFS", width=200, button_type="danger", icon="player-pause") @pn.depends(pause_button, watch=True) def _handle_pause_button(_): """ Pause the tariffs data to the original imposed tariffs. """ tariffs_rx.rx.value = pause_tariffs(tariffs_rx.rx.value) retaliate_button = pn.widgets.Button(name="RETALIATE ON CHINA", width=200, button_type="success", icon="flame") @pn.depends(retaliate_button, watch=True) def _handle_retaliate_button(_): """ Increase China Tariffs with 150%. """ tariffs_rx.rx.value = retaliate_china_tariffs(tariffs_rx.rx.value) # ============================================================================= # Custom JavaScript Component: Confetti Button # ============================================================================= class ConfettiButton(JSComponent): """ A custom Panel component that renders a button. When clicked, it triggers a confetti animation using an external JS module. """ factor = param.Number(0.5, allow_refs=True) _stylesheets = [ """ button { width: 100%; background: #F6D588; color: #0B162A; border: none; padding: 10px; border-radius: 4px; } button:hover { background: #F6D599; } """ ] _esm = """ import confetti from "https://esm.sh/canvas-confetti@1.6.0"; export function render({ model }) { let btn = document.createElement("button"); btn.innerHTML = "IMPOSE NOW. ❤️ TARIFFS."; btn.addEventListener("click", () => { const options = { scalar: 1.0 + 2.0 / model.factor, particleCount: 200 / model.factor, spread: 360 }; confetti(options); }); return btn; } """ # Create an instance of the confetti button confetti_button = ConfettiButton(factor=discount_factor, sizing_mode="stretch_width", margin=10) # ============================================================================= # Layout and Serve # ============================================================================= layout = pn.Column( "# Reciprocal Tariffs Calculator", pn.Row(reset_button, randomize_button, retaliate_button, pause_button), discount_factor, confetti_button, pn.pane.HTML(tariffs_rx.rx.pipe(create_tariffs_table)), width=1000, styles={"margin-right": "auto", "margin-left": "auto"}, stylesheets=["div: {background-color: #F6D588}"], ) layout.servable()