;;;====================================================== ;;; Financial Planning Expert System ;;; ;;; ;;; ;;; FuzzyCLIPS Version 6.0 Example ;;; ;;; To execute, merely load, reset, and run. ;;;====================================================== (defrule healthinsurance "if you don't have health insurance then insurance coverage is inadequate" (declare (cf 1.0)) (healthinsurance no) => (assert (basicinsurance inadequate)) ) (defrule lifeinsurance "if don't have life insurance when you should then insurance coverage is inadequate" (declare (cf 1.0)) (lifeinsurance no) (shouldhavelifeinsurance yes) => (assert (basicinsurance inadequate)) ) (defrule insurancecovered "if have life insureance and health insurance then insurance coverage is adequate" (declare (cf 1.0)) (healthinsurance yes) (lifeinsurance yes) => (assert (basicinsurance adequate)) ) (defrule shouldhavelifeinsurance1 "if you are married you should have life insurance" (declare (cf 1.0)) (married yes) => (assert (shouldhavelifeinsurance yes) ) ) (defrule shouldhavelifeinsurance2 "if you have kids you should have life insurance" (declare (cf 1.0)) (kids yes) => (assert (shouldhavelifeinsurance yes) ) ) (defrule getinsurancefirst "if you don't have adequate insurance you should take care of that before investing" (declare (cf 1.0)) (basicinsurance inadequate) => (assert (fundcatg None)) ) (defrule saveforrainyday "if your current savings are less than 6 months salary then keep liquid" (declare (cf 1.0)) (salary ?salary) (savings ?savings) (test (< ?savings (* ?salary 6))) => (assert (fundcatg MoneyMarket)) ) (defrule conservativegrowth "if saving for retirement and getting close to retirement then need conservative growth" (declare (cf 0.8)) (investmentgoal retirement) (yearstoretirement ?yrs) (test (<= ?yrs 10)) => (assert (fundcatg ConservativeGrowth)) ) (defrule growthandincome "if saving for retirement and intermediate range to retirement then need growth and income" (declare (cf 0.8)) (investmentgoal retirement) (yearstoretirement ?yrs) (test (and (<= ?yrs 20)(> ?yrs 10))) => (assert (fundcatg GrowthAndIncome)) ) (defrule aggressive "if saving for retirement and not close to retirement then need agressive" (declare (cf 0.8)) (investmentgoal retirement) (yearstoretirement ?yrs) (test (> ?yrs 20)) => (assert (fundcatg Aggressive)) ) (defrule growthandincome2 "if saving for childs education and child is less than 7 then need growth and income" (declare (cf 0.8)) (investmentgoal education) (ageoldestchild ?yrs) (test (< ?yrs 7)) => (assert (fundcatg GrowthAndIncome)) ) (defrule conservativegrowth2 "if saving for childs education and child is older than 7 then need conservative growth" (declare (cf 0.8)) (investmentgoal education) (ageoldestchild ?yrs) (test (>= ?yrs 7)) => (assert (fundcatg ConservativeGrowth)) ) (defrule growthandincome3 "if saving for a home then need growth and income" (declare (cf 0.9)) (investmentgoal home) => (assert (fundcatg GrowthAndIncome)) ) (defrule income "if saving for current income (retired) then need income" (declare (cf 0.9)) (investmentgoal income) => (assert (fundcatg Income)) ) (defrule conservativegrowth3 "if saving spare cash and risk tolerance is low then need conservative growth" (declare (cf 0.9)) (investmentgoal sparecash) (risktolerance low) => (assert (fundcatg ConservativeGrowth)) ) (defrule growthandincome4 "if saving spare cash and risk tolerance is medium then need growth and income" (declare (cf 0.8)) (investmentgoal sparecash) (risktolerance medium) => (assert (fundcatg GrowthAndIncome)) ) (defrule aggressive2 "if saving spare cash and risk tolerance is high then need aggressive" (declare (cf 0.8)) (investmentgoal sparecash) (risktolerance high) => (assert (fundcatg Aggressive)) ) (defrule taxfree "if saving spare cash and risk tolerance is medium and high tax bracket then need tax free" (declare (cf 0.9)) (investmentgoal sparecash) (risktolerance medium) (taxbracket high) => (assert (fundcatg TaxFree)) ) (defrule lifestage1 "if over 65 then probably retired" (declare (cf 0.8)) (age ?age) (test (>= ?age 65)) => (assert (lifestage retired)) ) (defrule lifestage2 "if under 65 then probably not retired" (declare (cf 0.8)) (age ?age) (test (< ?age 65)) => (assert (lifestage notretired) (yearstoretirement (- 65 ?age)) ) ) (defrule investmentgoal1 "if no pension and no ira then investment goal is retirement" (declare (cf 1.0)) (pension no) (ira no) => (assert (investmentgoal retirement) ) ) (defrule investmentgoal2 "if have children and children headed for college and childrens college not already funded then investment goal is college" (declare (cf 0.8)) (kids yes) (headedtocollege yes) (educationfunded no) => (assert (investmentgoal education) ) ) (defrule investmentgoal3 "if dont have a home and want a home then investment goal is home" (declare (cf 0.8)) (ownhome no) (wanthome yes) => (assert (investmentgoal home) ) ) (defrule investmentgoal4 "if life stage is retirement then investment goal is income" (declare (cf 0.9)) (lifestage retired) => (assert (investmentgoal income) ) ) (defrule haveretirementvehicle1 "if have a pension then have a retirement vehicle" (declare (cf 1.0)) (pension yes) => (assert (retirementvehicle yes) ) ) (defrule haveretirementvehicle2 "if have a ira then have a retirement vehicle" (declare (cf 1.0)) (ira yes) => (assert (retirementvehicle yes) ) ) (defrule homesatisfied1 "if own home then home goal satisfied" (declare (cf 1.0)) (ownhome yes) => (assert (homesatisfied yes) ) ) (defrule homesatisfied2 "if dont want to own home then home goal satisfied" (declare (cf 1.0)) (wanthome no) => (assert (homesatisfied yes) ) ) (defrule edusatisfied1 "if have no children then education goal satisfied" (declare (cf 1.0)) (kids no) => (assert (edusatisfied yes) ) ) (defrule edusatisfied2 "if childrens education already funded then education goal satisfied" (declare (cf 1.0)) (educationfunded yes) => (assert (edusatisfied yes) ) ) (defrule investmentgoal5 "if have everythinng else covered then investment goal sparecash" (declare (cf 0.8)) (homesatisfied yes) (retirementvehicle yes) (edusatisfied yes) (lifestage notretired) => (assert (investmentgoal sparecash) ) ) (defrule risk1 "if enjoy gambling then risk tolerance is high" (declare (cf 0.8)) (enjoygambling yes) => (assert (risktolerance high) ) ) (defrule risk2 "if budgeting is very important then risk tolerance is low" (declare (cf 0.8)) (budget important) => (assert (risktolerance low) ) ) (defrule risk3 "if worry about money at night then risk tolerance is low" (declare (cf 0.8)) (moneyworry yes) => (assert (risktolerance low) ) ) (defrule risk4 "if budget but splurge sometimes then risk tolerance is medium" (declare (cf 0.8)) (budget sometimes) => (assert (risktolerance medium) ) ) (defrule childrenheadedtocollege1 "if youngest child is 18 or less then there is a child headed to college" (declare (cf 1.0)) (kids yes) (ageyoungestchild ?yrs) (test (<= ?yrs 18)) => (assert (headedtocollege yes)) ) (defrule childrenheadedtocollege2 "if youngest child is over 18 then there is not a child headed to college (you better have already saved for it)" (declare (cf 1.0)) (kids yes) (ageyoungestchild ?yrs) (test (> ?yrs 18)) => (assert (headedtocollege no)) ) (defrule childrenheadedtocollege3 "if no children then there is not a child headed to college " (declare (cf 1.0)) (kids no) => (assert (headedtocollege no)) ) (defrule educationfunded1 "if child is going to a really cheap place then education is already funded" (declare (cf 1.0)) (kids yes) (tuition cheap) ;; really ??? => (assert (educationfunded yes)) ) (defrule educationfunded2 "if child has a scholarship then education is already funded" (declare (cf 1.0)) (kids yes) (scholarship yes) ;; really ??? like you would know in advance => (assert (educationfunded yes)) ) ;; wacko rule (defrule educationfunded3 "if child is eligible for loans then education is already funded" (declare (cf 1.0)) (kids yes) (loans eligible) => (assert (educationfunded yes)) ) (defrule educationfunded4 "if child has trust fund then education is already funded" (declare (cf 1.0)) (kids yes) (trustfund yes) => (assert (educationfunded yes)) ) (defrule educationfunded5 "if no funding options exist then education is not already funded" (declare (cf 1.0)) (kids yes) (scholarship no) (loans noteligible) (trustfund no) => (assert (educationfunded no)) ) ;;; MAR tax bracket rules - added 06/03/05 ;;; totally made up - I didn't check the tax code (defrule taxbracket1 " if monthly salary less than 1000 then tax bracket is low " (salary ?dollars) (test (< ?dollars 1000)) => (assert (taxbracket low)) ) (defrule taxbracket2 " if married and monthly salary less than 2000 then tax bracket is low " (married yes) (salary ?dollars) (test (< ?dollars 1000)) => (assert (taxbracket low)) ) (defrule taxbracket3 " if not married and monthly salary greater than 4000 then tax bracket is high " (married no) (salary ?dollars) (test (> ?dollars 4000)) => (assert (taxbracket high)) ) (defrule taxbracket4 " if married and monthly salary greater than 8000 then tax bracket is high " (married yes) (salary ?dollars) (test (> ?dollars 8000)) => (assert (taxbracket high)) ) (defrule taxbracket5 " if married and monthly salary between 2000 and 8000 then tax bracket is medium " (married yes) (salary ?dollars) (test (and (> ?dollars 2000) (< ?dollars 8000))) => (assert (taxbracket medium)) ) (defrule taxbracket6 " if not married and monthly salary between 1000 and 4000 then tax bracket is medium " (married no) (salary ?dollars) (test (and (> ?dollars 1000) (< ?dollars 4000))) => (assert (taxbracket medium)) ) (defrule answerrule " specify the answer with certainty factor" ?f <- (fundcatg ?answ) => (printout t t " The recommendation is " ?answ " with certainty factor " (get-cf ?f) t ) ) ;;; need to handle any fact ;;; but so far don't (defrule combineEvidenceRule " combine evidence reaching the same conclusion" ?f1 <- ( fundcatg ?val) ?f2 <- ( fundcatg ?val) ;;; same fact (test (not (eq ?f1 ?f2))) => (bind ?cf1 (get-cf ?f1)) (bind ?cf2 (get-cf ?f2)) (bind ?newcf (+ ?cf1 (* ?cf2 (- 1 ?cf1)))) (retract ?f1) (retract ?f2) (disable-rule-cf-calculation) ;; turn off rule cf calculations (assert (fundcatg ?val) cf ?newcf) (enable-rule-cf-calculation) ;; turn back on again ) ;;; handle risk tolerance need to handle any fact (defrule combineEvidenceRule2 " combine evidence reaching the same conclusion" ?f1 <- ( risktolerance ?val) ?f2 <- ( risktolerance ?val) ;;; same fact (test (not (eq ?f1 ?f2))) => (bind ?cf1 (get-cf ?f1)) (bind ?cf2 (get-cf ?f2)) (bind ?newcf (+ ?cf1 (* ?cf2 (- 1 ?cf1)))) (retract ?f1) (retract ?f2) (disable-rule-cf-calculation) ;; turn off rule cf calculations (assert (risktolerance ?val) cf ?newcf) (enable-rule-cf-calculation) ;; turn back on again )