@@ -146,7 +146,7 @@ def preprocess_puf(puf: pd.DataFrame) -> pd.DataFrame:
146146 puf ["educator_expense" ] = puf .E03220
147147 puf ["employment_income" ] = puf .E00200
148148 puf ["estate_income" ] = puf .E26390 - puf .E26400
149- puf ["farm_income" ] = puf .T27800
149+ puf ["farm_income" ] = puf .T27800 # Schedule J, separate from QBI
150150 puf ["health_savings_account_ald" ] = puf .E03290
151151 puf ["interest_deduction" ] = puf .E19200
152152 puf ["long_term_capital_gains" ] = puf .P23250
@@ -164,7 +164,12 @@ def preprocess_puf(puf: pd.DataFrame) -> pd.DataFrame:
164164 puf ["qualified_dividend_income" ] = puf .E00650
165165 puf ["qualified_tuition_expenses" ] = puf .E03230
166166 puf ["real_estate_taxes" ] = puf .E18500
167- puf ["rental_income" ] = puf .E25850 - puf .E25860
167+ puf ["rental_income" ] = puf .E25850 - puf .E25860 # Schedule E rent and royalty
168+ puf ["s_corp_income" ] = puf .E26190 - puf .E26180 # Schedule E active S-Corp income
169+ puf ["partnership_income" ] = puf .E25980 - puf .E25960 # Schedule E active partnership income
170+ puf ["farm_operations_income" ] = puf .E02100 # Schedule F active farming operations
171+ puf ["farm_rental_income" ] = puf .E27200 # Schedule E farm rental income
172+ puf ["self_employment_income" ] = puf .E00900 # Schedule C Sole Proprietorship
168173 puf ["self_employed_health_insurance_ald" ] = puf .E03270
169174 puf ["self_employed_pension_contribution_ald" ] = puf .E03300
170175 puf ["short_term_capital_gains" ] = puf .P22250
@@ -200,32 +205,19 @@ def preprocess_puf(puf: pd.DataFrame) -> pd.DataFrame:
200205 # Ignore f2441 (AMT form attached)
201206 # Ignore cmbtp (estimate of AMT income not in AGI)
202207 # Ignore k1bx14s and k1bx14p (partner self-employment income included in partnership and S-corp income)
203- # --- Qualified Business Income Deduction related variables ---
204- # Income sources
205- puf ["sole_proprietorship_net_income" ] = puf .E00900 # Schedule C Sole proprietorship income
206- puf ["farm_operations_net_income" ] = puf .E02100 # Schedule F active farming operations
207- puf ["farm_rental_net_income" ] = puf .E27200 # Schedule E farm rental income
208- puf ["rent_royalty_net_income" ] = puf .E25850 - puf .E25860 # Schedule E rent and royalty
209- puf ["estate_trust_net_income" ] = puf .E26390 - puf .E26400 # Schedule E estate or trust
210- puf ["s_corp_net_income" ] = puf .E26190 - puf .E26180 # Schedule E active S-Corp income
211- puf ["partnership_net_income" ] = puf .E25980 - puf .E25960 # Schedule E active partnership income
212-
213- puf ["reit_dividends" ] = 100
214- puf ["ptp_income" ] = 100 # Publically traded partnership income
215- puf ["bdc_dividends" ] = 100 # business development company income
216208
209+ # --- Qualified Business Income Deduction computation and simulation ---
217210 qbi = (
218- puf ["sole_proprietorship_net_income" ]
219- + puf ["schedule_F_farm_net_income" ]
220- + puf ["farm_rental_net_income" ]
221- + puf ["rent_royalty_net_income" ]
222- + puf ["estate_trust_net_income" ]
223- + puf ["s_corp_net_income" ]
224- + puf ["partnership_net_income" ]
211+ puf ["self_employment_income" ] # Schedule C sole prop
212+ + puf ["farm_operations_income" ] # NEW: schedule F active farming ops
213+ + puf ["farm_rental_income" ] # Schedule E farm rent: TODO: accidentally renamed farm_rent_income
214+ + puf ["rental_income" ] # Schedule E rent and royalty
215+ + puf ["estate_income" ] # Schedule E estate and trust
216+ + puf ["s_corp_income" ] # NEW: Schedule E S Corp # TODO: remake partnership_s_corp_income?
217+ + puf ["partnership_income" ] # NEW: Schedule E active partnership
225218 )
226219 print (f"QBI Est (Millions) New: { np .dot (qbi , puf .S006 ) / 1E6 :,.0f} " )
227220
228-
229221 def simulate_w2_wages_from_qualified_business (qbi , diagnostics = False ):
230222 MIN_MARGIN = .03
231223 MAX_MARGIN = .15
@@ -264,20 +256,22 @@ def simulate_w2_wages_from_qualified_business(qbi, diagnostics=False):
264256 print (f"Within positive QBI, proportion with W2 wages: { np .mean (w2_wages [qbi > 0 ]> 0 ):.2f} " )
265257 print (f"Within positive wages, mean in Millions is { np .mean (w2_wages [w2_wages > 0 ])/ 1E6 :.1f} " )
266258 print (f"Within positive wages, median in Millions is { np .median (w2_wages [w2_wages > 0 ])/ 1E6 :.1f} " )
267- print (f"Within positive wages, 75th percentile in Millions is { np .percentile (w2_wages [w2_wages > 0 ], 75 )/ 1E6 :.1f} " )
268- print (f"Within positive wages, max in Millions is { np .max (w2_wages [w2_wages > 0 ])/ 1E6 :.1f} " )
269- print (f"Within positive wages, median ubia property probability is { np .median (pr_has_qualified_property [w2_wages > 0 ]):.3f} " )
270- print (f"Within positive wages, median ubia property in millions is { np .median (ubia_property [w2_wages > 0 ])/ 1E6 :.1f} " )
259+ print (f"Within pos wages, 75th perc (mil) is { np .percentile (w2_wages [w2_wages > 0 ], 75 )/ 1E6 :.1f} " )
260+ print (f"For pos wages, max (mil) is { np .max (w2_wages [w2_wages > 0 ])/ 1E6 :.1f} " )
261+ print (f"For pos wages, med ubia >0 prob: { np .median (pr_has_qualified_property [w2_wages > 0 ]):.3f} " )
262+ print (f"For positive wages, med ubia prop (mil): { np .median (ubia_property [w2_wages > 0 ])/ 1E6 :.1f} " )
271263 return w2_wages , ubia_property
272264
273265 w2_wages , ubia_property = simulate_w2_wages_from_qualified_business (qbi )
274266 puf ["w2_wages_from_qualified_business" ] = w2_wages
275267 puf ["unadjusted_basis_qualified_property" ] = ubia_property
276268
277- # Business is SSTB
269+ # Simulate whether business is SSTB
278270 largest_qbi_source = np .argmax (puf [[
279- # 0: 20% 1: 0% 2: 15% 3: 0% 4: 0% 5: 0% 6: 10% 7: 10% 0%
280- "E00900" , "E02100" , "E26270" , "P25700" , "E25850" , "E27200" , "E26390" , "E26400" , "E02000" ]], axis = 1 )
271+ # 0: 20% 1: 0% 2: 15% 3: 0% 4: 0%
272+ "E00900" , "E02100" , "E26270" , "P25700" , "E25850" ,
273+ # 5: 0% 6: 10% 7: 10% 0%
274+ "E27200" , "E26390" , "E26400" , "E02000" ]], axis = 1 )
281275 largest_qbi_source = np .where (qbi <= 0 , - 1 , largest_qbi_source )
282276
283277 pr_sstb = np .where (largest_qbi_source == - 1 , 0 ,
@@ -294,8 +288,12 @@ def simulate_w2_wages_from_qualified_business(qbi, diagnostics=False):
294288
295289 pr_sstb = np .where (qbi < 1E-3 , 0 , pr_sstb )
296290 puf ["business_is_sstb" ] = np .random .binomial (n = 1 , p = pr_sstb )
297- # TODO: Fix the syntax:
298- #print(f"{100 * np.mean(puf.loc[qbi > 0]["business_is_sstb"]):.1f}% of pos businesses")
291+ print (f"SSTB %: { 100 * np .mean (puf .loc [qbi > 0 ]['business_is_sstb' ]):.1f} % of qbi pos biz" )
292+
293+ # TODO: improve
294+ puf ["reit_dividend_income" ] = 100
295+ puf ["ptp_income" ] = 100 # Publically traded partnership income
296+ puf ["bdc_dividend_income" ] = 100 # business development company income
299297
300298 # -------- End QBID work -------
301299 puf ["filing_status" ] = puf .MARS .map (
@@ -326,21 +324,23 @@ def simulate_w2_wages_from_qualified_business(qbi, diagnostics=False):
326324 "educator_expense" ,
327325 "employment_income" ,
328326 "estate_income" ,
327+ "farm_operations_income" ,
329328 "farm_income" ,
330- "farm_rent_income " ,
329+ "farm_rental_income " ,
331330 "health_savings_account_ald" ,
332331 "interest_deduction" ,
333332 "long_term_capital_gains" ,
334333 "long_term_capital_gains_on_collectibles" ,
335334 "unreimbursed_business_employee_expenses" ,
336335 "non_qualified_dividend_income" ,
337336 "non_sch_d_capital_gains" ,
338- "partnership_s_corp_income" ,
339337 "qualified_dividend_income" ,
340338 "qualified_tuition_expenses" ,
341339 "real_estate_taxes" ,
342340 "rental_income" ,
343341 "self_employment_income" ,
342+ "s_corp_income" ,
343+ "partnership_income" ,
344344 "self_employed_health_insurance_ald" ,
345345 "self_employed_pension_contribution_ald" ,
346346 "short_term_capital_gains" ,
@@ -374,6 +374,9 @@ def simulate_w2_wages_from_qualified_business(qbi, diagnostics=False):
374374 "unadjusted_basis_qualified_property" ,
375375 "business_is_sstb" ,
376376 "deductible_mortgage_interest" ,
377+ "reit_dividend_income" ,
378+ "ptp_income" ,
379+ "bdc_dividend_income"
377380]
378381
379382
0 commit comments