-
Notifications
You must be signed in to change notification settings - Fork 0
/
house_market_2009_UK.nlogo
3559 lines (2806 loc) · 122 KB
/
house_market_2009_UK.nlogo
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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
;extensions [profiler]
extensions [palette profiler]
;;;
;;; PwC Housing Market model
;;; Updated and heavily modified and commented by 深度碎片 EmbraceLife
;;; this updated model and notes can be downloaded from https://github.com/EmbraceLife/NetLogo-Modeling
;;; video tutorials on updating and understanding this model are available below
;;; Chinese version see Bilibili: https://www.bilibili.com/video/av31860025/
;;; English version see Youtube: https://www.youtube.com/playlist?list=PLx08F1efFq_XPiMl74IHpppb8NGqITLn2
;;; originally written by Nigel Gilbert, [email protected]
;;; the original model can be downloaded from http://cress.soc.surrey.ac.uk/housingmarket/ukhm.html
;;;
;;; Disclaimer
;;; This model has been prepared for general guidance on matters of interest only, and
;;; does not constitute professional advice. The results are purely illustrative. You
;;; should not act upon any results from this model without obtaining specific professional
;;; advice. No representation or warranty (express or implied) is given as to the accuracy
;;; or completeness of the model, and, to the extent permitted by law, PricewaterhouseCoopers,
;;; its members, employees and agents accept no liability, and disclaim all responsibility,
;;; for the consequences of you or anyone else acting, or refraining to act, in reliance on
;;; the model or for any decision based on it.
;;;
;;; This Housing Market model was developed by Nigel Gilbert with the assistance of John Hawksworth
;;; and Paul Sweeney of PricewaterhouseCoopers and is licensed under a
;;; Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License:
;;; <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/"><img alt="Creative Commons License" style="border-width:0" src="http://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" /></a><br /><span xmlns:dct="http://purl.org/dc/terms/" property="dct:title">Housing Market model</span> by <a xmlns:cc="http://creativecommons.org/ns#" href="http://cress.soc.surrey.ac.uk/housingmarket/ukhm.html" property="cc:attributionName" rel="cc:attributionURL">Nigel Gilbert</a> is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License</a>.
;;;
;;; To refer to this model in academic literature, cite:
;;; Gilbert, N, Hawksworth, J C, and Sweeney, P (2008) 'An Agent-based Model of the UK
;;; Housing Market'. University of Surrey http://cress.soc.surrey.ac.uk/housingmarket/ukhm.html
;;;
;;; version 0 NG 18 October 2007
;;; version 0.1 NG 09 November 2007
;;; version 0.2 NG 17 November 2007
;;; version 0.3 NG 23 November 2007 (bug: new entrants with zero mortgage)
;;; version 0.4 NG 08 December 2007 (bug: movers not recorded as being in new house;
;;; house prices reduced after no sale; purchasers
;;; only have upper bound limiting offer;
;;; entrants exit after a period if they can't find
;;; a house; realtors add a percentage on to the
;;; average price of local houses in forming their
;;; valuation
;;; version 0.5 NG 02 January 2008 New processes for realtor valuations and for
;;; making offers
;;; version 0.6 NG 26 January 2008 Added affordability, interest rate, house
;;; construction, sliders and code
;;; version 0.61 NG 11 February 2008 Added demolish proc to allow houses to die
;;; version 0.72 NG 24 March 2008 Redid house valuation to allow for quality
;;; version 0.8 JH, NG 4 April 2008 Adjusted initial parameters for more realistic
;;; behaviour
;;; NG 5 April 2008 Added gamma distribution for income, and income
;;; plot
;;; version 0.9 NG 17 April 2008 Added gini coefficient plot, changed display icons
;;; version 0.91 NG 18 April 2008 Added mortgage interest/income plot
;;; version 9.2 NG 19 April 2008 Added time on market plot, v. cheap houses get demolished
;;; version 10.2 NG 26 May 2008 Added gains from investment, re-did paint houses to
;;; use quantiles,
;;; re-did clustering, made sure realtors did not
;;; over-value
;;; version 10.4 NG 22 Jun 2008 Added fake realtor records at setup. Added correct
;;; mortgage interest calculations,
;;; inflation, slider for ticks per year
;;; version 1.1 NG 22 Jun 2008 Up and down shocks now defined in terms of
;;; Affordability, rather than hardwired numbers
;;; adjusted initial valuations to value houses for
;;; sale at start better
;;; version 1.2 NG 17 Jul 2008 Dealt with -ve equity, repayments > income, and
;;; further corrections to handling of mortgages.
;;; General tidy up. This is the version used for the
;;; ESSA paper
;;; version 1.3 NG 5 Sept 2008 1st time buyers get fixed capital
;;; version 1.4 NG 6 Sept 2008 Added initial savings slider and disclaimer
;;; version 1.5 NG 20 Jun 2011 Upgraded to work with NetLogo 1.4.3
;;; version 1.6 NG 21 Dec 2013 Upgraded to NetLogo 5.0.4 and open sourced under a Creative Commons licence
;;; version 1.61 NG 24 Jan 2013 Corrected bug introduced in upgrading to NL 5.0.4
;;; version 1.7 深度碎片 2 Oct 2018 corrected bug introduced in upgrading to NL 6.0.4 with many tiny modifications and heavily commented.
globals [
; scenario ; to illustrate various step changes
;; these could become sliders
initialVacancyRate ; proportion of empty houses at start
nRealtors ; number of realtors
min-price-fraction ; if a house price falls below this fraction of the median price, it is demolished
; globally accessible variables (mainly here as globals so that they can be plotted)
moves ; number of households moving in this step
interestPerTick ; interest rate, after cyclical variation has been applied
nUpshocked ; number of owners putting their house for sale because their income has risen
nDownshocked ; number of owners putting their house for sale because their income has dropped
nDemolished ; number of houses demolished in this step
medianPriceOfHousesForSale ; guess!
nDiscouraged ;; number of owners who discouraged by homeless and leave the city
nExit ;; number of owners who naturally leave the city or cease to exist
nEntry ;; number of owners who naturally enter or born into the city
nForceOut ;; number of owners whose repayment is greater than income and force to leave
nOriginalOwners ;; original number of owners at beginning
nOwnersOffered ;; number of owners who made an offer on a house (have enough money and have target to buy)
meanIncomeForceOut ;; cal the mean income of all owners who are forced out due to low income to repay mortgage
]
breed [houses house ] ; a house, may be occupied and may be for sale
breed [owners owner ] ; a household, may be living in a house, or may be seeking one
breed [realtors realtor ] ; an estate agent
breed [records record ] ; a record of a sale, kept by realtors
;breed [exits exit] ;; avoid to use die or nobody, put dead agents into this breed
houses-own [
my-owner ; the owner who lives in this house
local-realtors ; the local realtors
quality ; index of quality of this house relative to its neighbours
for-sale? ; whether this house is currently for sale
sale-price ; the price of this house (either now, or when last sold)
date-for-sale ; when the house was put on the market
my-realtor ; if for sale, which realtor is selling it
offered-to ; which owner has already made an offer for this house
offer-date ; date of the offer (in ticks)
end-of-life ; time step when this house will be demolished
]
owners-own [
my-house ; the house which this owner owns
income ; current income
mortgage ; value of mortgage - reduces as it is paid off
capital ; capital that I have accumulated from selling my house
repayment ; my mortgage repayment amount, at each tick
date-of-purchase ; when my-house was bought
made-offer-on ; house that this owner wants to buy
homeless ; count of the number of periods that this owner has been
; without a house
]
realtors-own [
my-houses ; the houses in my territory
sales ; the last few house sales that I have made
average-price ; the average price of a house in my territory
]
records-own [ ; object holding a realtor's record of a transaction
the-house ; the house that was sold
selling-price ; the selling price
date ; the date of the transaction (in ticks)
]
to setup
clear-all
reset-ticks
;; we can experiment on one of five scenarios (analysis)
;; the choise is given in go procedure
; if scenario = "ltv" [ set MaxLoanToValue 60 ]
; if scenario = "ratefall" [ set InterestRate 3 ]
; if scenario = "influx" [ set EntryRate 10 ]
; if scenario = "poorentrants" [ set MeanIncome 24000 ]
; if scenario = "clusters", continue for 400 steps
;; initialise globals (in code, but there are globals in interface to be initialized as well )
set initialVacancyRate 0.05
set nRealtors 6 ;; original is 6, I shrink the size of agents (all kinds)
set maxHomelessPeriod 5
set interestPerTick InterestRate / ( TicksPerYear * 100 ) ;; meaning clarified in note
set min-price-fraction 0.1
if scenario = "base-line" [
set Inflation 0 ;; inflation rate 0 or 2
set InterestRate 7 ;; 7 as 7% per year
set TicksPerYear 4 ;; 4 ticks = a year
set CycleStrength 0 ;; how much variation (0) is introduced to interest rate
set Affordability 25 ;; 25% of income can be used to pay for mortgage
set Savings 50 ;; 50% of income will be saved
set ExitRate 2 ;; 2% of owners will exit city due to death or relocation of job each tick
set EntryRate 5 ;; 5% of owners are new comers enter the city each tick
set MeanIncome 30000 ;; mean income of whole population is 30000, used to calc each person's income using a gamma distribution
set Shocked 20 ;; 20% of whole population will get an income shock (either up or down)
set MaxHomelessPeriod 5 ;; maximum duration of homeless any one can stand before exit the city
set BuyerSearchLength 10 ;; any buyer will only have patience to shop around maximum 10 houses
set RealtorTerritory 8 ;; realtor's territory is a circle with radius equal to 8 units
set Locality 3 ;; local neighbors to a house is all the houses within 3 units distance to it
set RealtorMemory 10 ;; any record can only live for 10 ticks
set PriceDropRate 3 ;; if not sold at current tick, then drop sale-price by 3%
set RealtorOptimism 3 ;; when doing a valuation for a house, raise valuation by 3% due to realtor's optimism
set Density 70 ;; 70% of land are filled with houses
set HouseMeanLifetime 100 ;; the end of life of a house is determined by a exponential distribution using the mean lifetime of all houses (100 years)
set MaxLoanToValue 100 ;; maximum mortgage / house sale-price = 100% = 1
set StampDuty? false ;; do not consider StampDuty
set MortgageDuration 25 ;; mortgage taks 25 years to repay
set HouseConstructionRate 0.33 ;; each tick build new houses equal to 0.33% of current total houses
set Income-shock 20 ;; income shock is to rise or fall by 20%
set InitialGeography "Random" ;; houses are located randomly, not by gradient nor cluster
set price-difference 5000 ;; in cluster mode, consider houses whose price is more than 5000 differ from their neighbor houses, belong to different clusters
set scenario "base-line" ;; automatically set all parameters to base line values
set initialVacancyRate 0.05 ;; at the very beginning there are 5% of houses are empty
set nRealtors 6 ;; there are 6 realtors in the city
set min-price-fraction 0.1 ;; when the sale-price of a house drop to 10% of median price of all houses, make this house demolished.
set interestPerTick InterestRate / ( TicksPerYear * 100 ) ;; convert interest rate per year to interest rate per tick
set house-alpha 251 ;; no transparency
set debug-setup "none"
set debug-go "none"
set exp-options "none"
]
; no-display ;; to make setup run faster, avoid display in process (given continous mode rather than tick mode)
;; 1. patches ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; make the world or land light gray from color swatches
ask patches [ set pcolor gray + 3 ]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
if debug? or debug-setup = "1 patches" [
inspect patch 1 1
user-message (word "1 patches : loop each patch, paint it muddy green. ")
stop-inspecting patch 1 1
]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 2 realtors ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; create and distribute the realtors (estate agents)
set-default-shape realtors "flag" ;;
let direction random 360
create-realtors nRealtors [ ;; create one at a time, totally nRealtors
set color yellow
; distribute realtors in a rough circle
set heading direction
jump (max-pxcor - min-pxcor) / 4 ;; jump outward by 1/4 of length of the world
set direction direction + 120 + random 30 ; prepare direction of jump for the next realtor
set size 1 ;; original 3, here only 1 is visually good
; draw a circle to indicate a realtor's territory
draw-circle RealtorTerritory ;; RealtorTerritory is slider global variable
]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; if debug? or debug-setup = "2 realtors" [
; inspect min-one-of realtors [who]
; user-message (word "2 realtors : build realtors with flags, and draw circles as territory ")
; stop-inspecting min-one-of realtors [who]
; ]
if exp-options = "realtor" [
ask realtor 0 [
inspect self
type "this realtor is just created. " print ""
user-message (word "")
]
]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 3 houses;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; create and distribute the houses
repeat (count patches * Density / 100) [ build-house ]
;; Density=70% is a slider global variable for houses, 70 houses on 100 patches, use this ratio to create enough houses for this world
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; if debug? or debug-setup = "3 houses" [
; inspect max-one-of houses [who]
; user-message (word "3 houses : build a number of houses. Check which properties are initialized. " )
; stop-inspecting max-one-of houses [who]
; ]
if exp-options = "houseStory" [
ask one-of houses [
set size 3
show "I am a house just created!----------------------------------------------------------------------------------------------------"
show (word "my ID : " who ", my-owner : " my-owner ", local-realtors : " [who] of local-realtors ", my-realtor : " my-realtor )
show (word ", for-sale : " for-sale? ", quality : " precision quality 1 ", sale-price : " precision sale-price 1 ", date-for-sale : " date-for-sale )
show (word ", offered-to : " offered-to ", offer-date : " offer-date ", end-of-life : " end-of-life ", my-size : " size)
print ""
]
]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 4 owners: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; create the owners, one per house
set-default-shape owners "dot" ;; all owners are dots
let occupied-houses n-of ((1 - initialVacancyRate) * count houses) houses ;; randomly take (1 - initialVacancyRate) proportion of houses to be `occupied-houses`
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
if exp-options = "houseStory" and not member? 3 [size] of occupied-houses
[
show "I am not selected to be the occupied houses at first. ----------------------------------------------------------------------------------------------------"
print ""
]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ask occupied-houses [ ;; define each home-owner's properties
set for-sale? false ;; since owners living inside, it should not for-sale now
hatch-owners 1 [ ;; create an owner inside this house
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; if debug? or debug-setup = "4 owners" [
;
; inspect self
; inspect one-of houses-here ;; here refers to patch underneath
;
; user-message ( word " 4 owners : it is a bare owner " )
; ]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
set color red ;; make owner red
set size 0.7 ;; owner easy to see but not too big
set my-house myself ;; owner claims its house
ask my-house [set my-owner myself ] ;; ask the house to claim its owner
assign-income ;; create income and capital for owner
if InitialGeography = "Gradient" [ set income income * ( xcor + ycor + 50) / 50 ] ;; income increase from bottom-left to top-right
set mortgage income * Affordability / ( interestPerTick * ticksPerYear * 100 ) ;; create mortgage
let deposit mortgage * ( 100 / MaxLoanToValue - 1 ) ;; create deposit
ask my-house [ set sale-price [mortgage] of myself + [deposit] of myself ] ;; create sale-price = mortgage + deposit for the house
set repayment mortgage * interestPerTick /
(1 - ( 1 + interestPerTick ) ^ ( - MortgageDuration * TicksPerYear ))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; if debug? or debug-setup = "4 owners" [
;
; user-message (word "4 owners : build an owner, initialize properties to owner and its house. " )
;
; stop-inspecting self
; stop-inspecting one-of houses-here
; ]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
if exp-options = "houseStory" [
if size = 3 [
show "I am selected to be an occupied house, and an owner is born to me, and now I am not for sale! --------------------------------------------------"
show (word " my sale-price = owner's mortgage (" precision [mortgage] of my-owner 1 ") + deposit (" precision ([mortgage] of my-owner * ( 100 / MaxLoanToValue - 1 )) 1 ") = " precision sale-price 1)
show (word "my ID : " who ", my-owner : " my-owner ", local-realtors : " [who] of local-realtors ", my-realtor : " my-realtor )
show (word ", for-sale : " for-sale? ", quality : " precision quality 1 ", sale-price : " precision sale-price 1 ", date-for-sale : " date-for-sale )
show (word ", offered-to : " offered-to ", offer-date : " offer-date ", end-of-life : " end-of-life ", my-size : " size)
print "----------------------"
let owner-me [my-owner] of one-of houses with [size = 3]
show (word "my-owner : " owner-me ", income : " precision [income ] of owner-me 1 ", capital : " precision [capital] of owner-me 1 ", mortgage : "precision [mortgage] of owner-me 1 ", my-house : " [my-house] of owner-me)
print ""
]
]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
]
set nOriginalOwners count owners
paint-houses ;; since houses got prices, let's paint houses
;; 5 empty ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; For vacant houses, without owners, those houses have no sale-prices, my-owner properties
let ln-min-price precision ln [sale-price] of min-one-of houses with [ sale-price != 0 ] [sale-price] 1 ;; copy ln-min-price from paint-houses
let ln-max-price precision ln [sale-price] of max-one-of houses with [ sale-price != 0 ] [sale-price] 1
let median-price median [ sale-price ] of houses with [ sale-price > 0 ] ;; median sale-prices of all houses with owners
ask houses with [ sale-price = 0 ] [ ;; loop each empty house
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; if debug? or debug-setup = "5 empty" [
;
; inspect self ;; check bare empty house
; user-message (word "5 empty : check a bare empty house, to initialize my-owner, sale-price, and color it up " )
; ]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
set my-owner nobody ;; my-owner from 0 to nobody
let local-houses houses with [distance myself < Locality and sale-price > 0]
;; find all local houses of the empty house = locality distance and has owner with sale-price
ifelse any? local-houses ;; if there exist local houses,
[ set sale-price median [ sale-price ] of local-houses ] ;; use local houses median price as the empty house sale-price
[ set sale-price median-price ] ;; otherwise, use all occupied houses median price for the empty house sale-price
set color palette:scale-scheme "Divergent" "Spectral" 5 (ln sale-price) ln-min-price ln-max-price ;; borrow it from paint-houses to color the empty house
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; if debug? or debug-setup = "5 empty" [
;
; user-message (word "5 empty : No more a bare house, check my-owner, sale-price, and new color. " )
; stop-inspecting self
; ]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
if exp-options = "houseStory" [
if size = 3 [
show "I am an empty house (stay for-sale) and need to get a sale-price ! --------------------------------------------------"
show (word "my sale-price is determined by all occupied sale-prices : " not any? local-houses ", or just local-occupied-sale-prices : " any? local-houses )
show (word "my ID : " who ", my-owner : " my-owner ", local-realtors : " [who] of local-realtors ", my-realtor : " my-realtor )
show (word ", for-sale : " for-sale? ", quality : " precision quality 1 ", sale-price : " precision sale-price 1 ", date-for-sale : " date-for-sale )
show (word ", offered-to : " offered-to ", offer-date : " offer-date ", end-of-life : " end-of-life ", my-size : " size)
print ""
]
]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
]
if InitialGeography = "Clustered" [ cluster ] ;; move houses to the neighbors with similar prices
;; 7 quality ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
set medianPriceOfHousesForSale median [sale-price] of houses ;; get median price for all houses
ask houses [
set quality sale-price / medianPriceOfHousesForSale ;; quality is sale-price/median-price
if quality > 3 [set quality 3] if quality < 0.3 [set quality 0.3] ;; quality is between 0.3 to 3
; set color scale-color magenta quality 0 5 ;; quality by magenta scale
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
if exp-options = "houseStory" [
if size = 3 [
show "I am updating my house quality, everyone too ! --------------------------------------------------"
show (word "quality is sale-price / medianPriceOfAllHouses ")
show (word "my ID : " who ", my-owner : " my-owner ", local-realtors : " [who] of local-realtors ", my-realtor : " my-realtor )
show (word ", for-sale : " for-sale? ", quality : " precision quality 1 ", sale-price : " precision sale-price 1 ", date-for-sale : " date-for-sale )
show (word ", offered-to : " offered-to ", offer-date : " offer-date ", end-of-life : " end-of-life ", my-size : " size)
print ""
]
]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; if debug? or debug-setup = "7 quality" [
;
; inspect max-one-of houses [ who ]
; user-message (word "7 quality: initialize quality of house, based on sale-price " )
; stop-inspecting max-one-of houses [ who ]
; ]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 9 realtors ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; initialize sales, my-houses, average-price
ask realtors [
set sales [] ;; take sales as empty list
set my-houses houses with [member? myself local-realtors ] ;; take all houses having the realtor as one of their local-realtors to be my-houses
set average-price median [ sale-price ] of my-houses ;; take median price of my-houses to be average-price
]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; if debug? or debug-setup = "9 realtors: my-houses, avg-price" [
; inspect max-one-of realtors [ who ]
; user-message (word "9 realtors: initialize sales, my-houses, average-price for realtors ")
; stop-inspecting max-one-of realtors [ who ]
; ]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 10 records;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; create records for each and every house
;; at the start, every house is assumed to be sold previously and has a record
;; the house's sale-price is the record's selling-price,
;; my-realtor is set randomly at the start, and this realtor will store the record into its sales list
ask houses [ ;; loop each house
let the-record nobody ;; `the-record` is nobody
hatch-records 1 [ ;; hatch a record from a house
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; if debug? or debug-setup = "10 records" [
; inspect myself ;; inspect the current house
; inspect self ;; inspect the current record
; user-message (word "10 records : initialize the-house, selling-price for current record; initialize my-realtor for current house; update sales for my-realtor. ")
; ]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
hide-turtle ;; hide the current record
set the-house myself ;; take the current house to be the-house of the current record
set selling-price [ sale-price ] of myself ;; take the sale-price of the house to be selling-price of the current record
set the-record self ;; use the-record to carry the current record outside the hatch function into the house context
]
set my-realtor one-of local-realtors ;; randomly take one of the local-realtors to be my-realtor of the current house
ask my-realtor [ file-record the-record ] ;; ask my-realtor to save the current record (the-record) into sales of my-realtor
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; if debug? or debug-setup = "10 records" [
;
; inspect my-realtor
; user-message (word "10 records : initialize the-house, selling-price for current record; initialize my-realtor for current house; update sales for my-realtor. ")
; stop-inspecting self
; stop-inspecting the-record
; stop-inspecting my-realtor
; ]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
if exp-options = "houseStory" [
if size = 3 [
show "I am having a record, and everyone too ! --------------------------------------------------"
show (word "see my record, update my-realtor, let my-realtor keep my record")
show (word "my ID : " who ", my-owner : " my-owner ", local-realtors : " [who] of local-realtors ", my-realtor : " my-realtor )
show (word ", for-sale : " for-sale? ", quality : " precision quality 1 ", sale-price : " precision sale-price 1 ", date-for-sale : " date-for-sale )
show (word ", offered-to : " offered-to ", offer-date : " offer-date ", end-of-life : " end-of-life ", my-size : " size)
show (word "my record's ID : " [who] of the-record ", has the-house : " [the-house] of the-record ", selling-price : " precision [selling-price] of the-record 1 )
show (word "my-realtor has stored my-record : " [sales] of my-realtor )
print ""
]
]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
]
;; to experiment for verification
experiments
paint-houses
display
do-plots
reset-ticks
end
;; create random income and capital for an owner ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
to assign-income
;; an owner's income is a random number from a particular gamma distribution
;; an owner's capital is a proportion of income
;; income distribution formula is based on the following paper
;; parameters taken from http://www2.physics.umd.edu/~yakovenk/papers/PhysicaA-370-54-2006.pdf
let alpha 1.3
let lambda 1 / 20000
set income 0
; avoid impossibly low incomes (i.e. less than half the desired mean income)
while [ income < MeanIncome / 2 ] [ ;; as long as income is less than half of median income
set income (MeanIncome * lambda / alpha ) * (random-gamma alpha lambda) *
(1 + (Inflation / (TicksPerYear * 100)) ) ^ ticks ;; redefine income value with this equation (check the paper for details )
]
; give them a proportion of a year's income as their savings
set capital income * Savings / 100 ;; save up money or captial for buying houses every year
end
;; 2.5 build-a-house ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; created houses, make sure one patch one house, one house has at least one realtor, house for sale at first, set demolish-time
to build-house
set-default-shape houses "my-house" ;; I changed the design of a house
create-houses 1 [
; hide-turtle ;; original code, but I don't like house to be hidden
set color 35 ;; set house to be brown
;; How to make transparent color ?
set color lput house-alpha extract-rgb color
; for speed, dump the house anywhere, check if there is already a house there,
; and if so, move to an empty spot
move-to one-of patches
if count houses-here > 1 [ ;; if more than 1 houses on the current patch ;; houses-here == turtles-here, check document
; user-message ( word "count houses-here > 1 is true, how many inside houses-here? " count houses-here )
let empty-sites patches with [ not any? houses-here ] ;; ask every patch to see whether it already has a house on it or not, if not consider it an empty-site
; user-message ( word "let empty-sites patches with [ not any? houses-here ], length empty-sites" count empty-sites) ;; debug for details
if any? empty-sites [ move-to one-of empty-sites ] ;; if empty-sites exist, let current house move to any one of the empty-site
]
; assign to a realtor or realtors if in their territory
set local-realtors realtors with [ distance myself < RealtorTerritory ] ;; if the realtor to the house distance < radius, make the realtor(s) for the house
; if no realtor assigned, then choose nearest
if not any? local-realtors [ set local-realtors turtle-set min-one-of realtors [ distance myself ] ] ;; turtle-set to check
put-on-market ; initially empty houses are for sale
; note how long this house will last before it falls down and is demolished
set end-of-life ticks + int random-exponential ( HouseMeanLifetime * TicksPerYear )
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
if debug? or debug-setup = "2.5 build-a-house" [
inspect self
user-message (
word "2.5 build-a-house : create a single house, paint it brown, make it transparent, move it a random patch without house, find local-realtors, "
word "or just a nearest realtor, put on market for sale, calc end-of-life with random-exponential" "."
)
stop-inspecting self
]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
]
end
to put-on-market ;; house procedure
;; show that this house is for sale
set for-sale? true
set date-for-sale ticks
end
to draw-circle [radius] ;; the current realtor turtle will create a new turtle to draw a circle as territory
;; draw the circumference of a circle at the given radius
hatch 1 [ ;; based on current turtle, let's create/hatch a new turtle which inherit its parent's properties
set pen-size 1 set color yellow set heading -90 fd radius ;; set up pen size, color and radius for drawing a circle
set heading 0 ;; set the heading to be tanget line direction
pen-down
while [heading < 359 ] [ rt 1 fd (radius * sin 1) ] ;; drawing a circle, see the debug proof below
; user-message (word "finished drawing circle ? ") ;; yes, this is debugging
die ;; end the drawing turtle
]
end
;; 11 paint-log-price ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; scale-paint houses according to log of sale-price
to paint-houses
let min-price precision [sale-price] of min-one-of houses with [ sale-price != 0 ] [sale-price] 1
let ln-min-price precision ln [sale-price] of min-one-of houses with [ sale-price != 0 ] [sale-price] 1
let max-price precision [sale-price] of max-one-of houses with [ sale-price != 0 ] [sale-price] 1
let ln-max-price precision ln [sale-price] of max-one-of houses with [ sale-price != 0 ] [sale-price] 1
ask houses with [ sale-price != 0 ] [ ;; maybe set empty house initial 0 price to "0" ?
if debug? or debug-setup = "11 paint-log-price" [
follow-me
user-message (word " 11 paint-log-price : loop each house , paint each house with divergent colors based on log sale-prices " )
]
set color palette:scale-scheme "Divergent" "Spectral" 5 (ln sale-price) ln-min-price ln-max-price
; scale-scheme "Divergent" "RdYlBu" 10 ; the number 10 control how many different colors in between, 5 may be the best
; good color options: "Spectral" "RdYlBu" "RdYlGn"
;; ok color options : PiYG PRGn PuOr RdBu RdGy
;; set color scale-color red ln sale-price ln-min-price ln-max-price
set color lput house-alpha color ;; add transparency to color
if debug? or debug-setup = "11 paint-log-price" [
user-message (word " 11 paint-log-price : loop each house , paint each house with divergent colors based on log sale-prices " )
]
]
end
;; 6 cluster ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
to cluster
;; cluster houses together based on price similarity
repeat 3 [ ;; cluster all all houses three times
paint-houses ;; scale-paint houses based on log sale-price
let houses-to-move sort-by [ [ house1 house2 ] -> price-diff house1 > price-diff house2 ] houses ;; new-version
;; reorder every house based on price-difference to its neighbor houses, largest first, smallest last
foreach houses-to-move [ ;; loop each house
x -> if price-diff x >= price-difference [ ;; if current house price is way too different from its surroundign houses
let vacant-plot one-of patches with [ ;; get one of many empty patches, where
not any? houses-here and ;; there is no house built
abs (local-price - [ sale-price ] of x ) < 1000 ] ;; where the surrounding house prices is similar to the current house
if vacant-plot != nobody [ ;; if those empty patches do exist
ask x [ ;; ask this current house
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
if debug? or debug-setup = "6 cluster" [
pd set pen-size 2 ;; put pen down to draw a track
if is-owner? my-owner [
ask my-owner [ follow-me ] ;; watch the owner ( can't use watch-me here)
]
user-message (word "6 cluster : the house move with a track line, the owner is watched. " )
]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
move-to vacant-plot ;; to move to one of the empty patch
if is-owner? my-owner [ ;; whether it got an owner, if so
ask my-owner [ move-to myself ] ;; ask the owner move to where the house is
]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
if debug? or debug-setup = "6 cluster" [
user-message (word "6 cluster : the house move with a track line, the owner is watched. " )
pen-up ;; pull pen up
]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
]
]
]
]
]
end
;; find out median price for local houses ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
to-report local-price
let local-houses houses-on neighbors ;; based on the current patch, looking for its eight neighbor patches, put all the houses on those patches under `local-houses`
ifelse any? local-houses ;; if `loca-houses` is not empty
[ report median [sale-price] of local-houses ] ;; report median price of all neighbor houses' sale-prices to be `local-price`
[ report 0 ] ;; if no neighbor houses, report 0 to be `local-price`
end
;; find out the price difference between a house and its neighbors ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
to-report price-diff [ a-house ]
report abs ([sale-price] of a-house - [local-price] of a-house) ;; Note the use [ local-price ] of a-house
end
;; experiment for verification ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
to experiments
if exp-options = "track-owner-numbers" [
type "nOriginalOwners: " type nOriginalOwners type " owner without house: " type count owners with [not is-house? my-house ]
type " nOwnersOffered: " type nOwnersOffered ;; each tick how many owners can afford a targeted house to buy
type " owners now: " type (count owners) type " exit: " type nExit
type " entry: " type nEntry type " nDiscouraged: " type nDiscouraged type " nForceOut: " type nForceOut print ""
]
if exp-options = "track-houses-sales-numbers" [
let sum-sales 0 ask realtors [ set sum-sales sum-sales + length sales] show sum-sales
let sum-houses 0 ask realtors [ set sum-houses sum-houses + count my-houses] show sum-houses
type "total houses: " type count houses type ", total sales: " type sum-sales type ", total houses under 3 realtors (include duplicated) : " type sum-houses print ""
]
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
to go
set nDiscouraged 0
set nExit 0
set nEntry 0
set nForceOut 0
set nOwnersOffered 0
set meanIncomeForceOut 0 ;; get mean income of owners who are forced out
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; if debug? or debug-go = "s0 go-structure" [
; user-message (word "s0 go-structure : set simulation duration, half time bring in a scenario, one step per go, 3 conditions to stop simulation. Now let's run! ")
; ]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; basic loop
if ticks > 400 [
print "Finished: 400 ticks reached "
stop ]
if ticks = 200 [
if scenario = "ltv" [ set MaxLoanToValue 60 ]
if scenario = "raterise 3" [ set InterestRate 3 ]
if scenario = "raterise 7" [ set InterestRate 7 ]
if scenario = "raterise 10" [ set InterestRate 10 ]
if scenario = "influx" [ set EntryRate 10 ]
if scenario = "influx-rev" [ set EntryRate 5 ]
if scenario = "poorentrants" [ set MeanIncome 24000 ]
type "We are at middle of simulation duration, ticks = " type ticks type ", a shock event coming in := " type scenario print ";"
]
set nOwnersOffered 0
step ;; do one time step (a quarter of a year?)
if not any? owners [ user-message(word "Finished: no remaining people" ) stop ] ;; stop if no owners or houses left
if not any? houses [ user-message(word "Finished: no remaining houses" ) stop ]
do-plots ;; update the plots
;; experiment for verification
experiments
tick ;; advance the clock
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
to step
;; each time step...
;; count total number of owners ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
let n-owners count owners ;; take a count of total owners at the moment
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
if exp-options = "houseStory" [
show (word "I am at step: " ticks ", count total owners : " n-owners)
print ""
]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; calc interest per tick ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; add an exogenous cyclical interest rate, if required: varies around mean of
; the rate set by slider with a fixed period of 10 years
set interestPerTick InterestRate / ( TicksPerYear * 100 )
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
if exp-options = "houseStory" [
show (word "The year interest : " InterestRate ", converted to interstPerTick: " interestPerTick)
print ""
]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; add cyclical variation to interest ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
if CycleStrength > 0 [
set interestPerTick interestPerTick * (1 + (CycleStrength / 100 ) * sin ( 36 * ticks / TicksPerYear )) ]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
if exp-options = "houseStory" [
show (word "Cyclical variation on interestRate is introduced? : " (CycleStrength > 0) ", how big is the variation : " CycleStrength )
print ""
]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; inflation drive up income ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; add inflation to salary, at inflation rate / TicksPerYear
ifelse Inflation > 0 [
ask owners [
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; if debug? or debug-go = "s4 inflation-income" [
; inspect self
; user-message ( word "4 inflation-income : inflation will drive up income accordingly. " precision income 1)
; ]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
set income income * (1 + Inflation / ( TicksPerYear * 100 )) ;; every tick, income stay the same or varied by inflation
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
if exp-options = "houseStory" and is-turtle? my-house and [size] of my-house = 3 [
show (word "I am me : " my-house ", my-owner is : " self ", its income is affected by inflation. ----------------------------- " )
show (word "Inflation is introduced? : " (Inflation > 0) ", how much is the inflation : " Inflation ", income is raised upto : " precision income 1)
print ""
]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
]
]
[
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
if exp-options = "houseStory" [
show (word "Inflation is introduced? : " (Inflation > 0) ", there is no effect on income by inflation. ----------------------------" )
print ""
]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
]
;; get all the owners with houses ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
let owner-occupiers owners with [ is-house? my-house ]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; if debug? or debug-go = "s5 owner-occupiers" [ user-message (
; word "s5 owner-occupiers : bring all owners with houses under variable `owner-occupiers`. the count = " count owner-occupiers ) ]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; introduce income rise and fall shock to owners ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
let shocked-owners n-of (Shocked / 100 * count owner-occupiers ) owner-occupiers ;; gather Shocked% of `owner-occupiers` under `shocked-owners`
let upshocked n-of (count shocked-owners / 2) shocked-owners ;; gather half of `shocked-owners` under `upshocked`
set nUpShocked 0 ;; initialize the number of upshocked owners under `nUpShocked`
ask upshocked [ set income income * (1 + income-shock / 100) ] ;; ask each `upshocked` to increase income by 20%
let downshocked shocked-owners with [ not member? self upshocked ] ;; gather the non-upshocked as down shocked owners under `downshocked`
set nDownShocked 0 ;; initialize the number of upshocked owners under `nUpShocked`
ask downshocked [ set income income * (1 - income-shock / 100 ) ] ;; ask each downshocked to drop income by 20%
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; if debug? or debug-go = "s6 income-shock" [
; user-message (
; word "s6 income-shock : each tick, a Shocked% of home-owners got income shock = " Shocked
; word "; half income rise income-shock% the other drop income-shock% = " income-shock
; )
; ]
if exp-options = "houseStory" [
ask houses with [size = 3] [
show (word "My breed is " breed ", and I am checking on my-owner's incomeShock situation ---------------------------------------------------" )
show (word "my ID : " who ", my-owner : " my-owner ", local-realtors : " [who] of local-realtors ", my-realtor : " my-realtor )
show (word ", for-sale : " for-sale? ", quality : " precision quality 1 ", sale-price : " precision sale-price 1 ", date-for-sale : " date-for-sale )
show (word ", offered-to : " offered-to ", offer-date : " offer-date ", end-of-life : " end-of-life ", my-size : " size)
if my-owner != nobody and member? my-owner upshocked [ show (word "my-owner belongs to the upshocked group, my owner's income has increased by " income-shock "% upto : " precision [income] of my-owner 1 )]
if my-owner != nobody and member? my-owner downshocked [ show (word "my-owner belongs to the downshocked group, my owner's income has decreased by " income-shock "% downto : " precision [income] of my-owner 1 )]
if my-owner != nobody and not member? my-owner shocked-owners [ show (word "my-owner income has not been shocked, and still at " precision [income] of my-owner 1 )]
]