Moderator: MacroQuest Developers

Code: Select all
|Update Bazaar Prices
|by Sparr
|
|this macro updates the prices on all your /trader items to compete
| with other prices found via /bazaar
|
|rare items are priced 1 standard deviation below the average price, minus 1
|common items are priced the median of the below avg prices, minus 1
|
|price is then upped to 1pp below the next higher price
|
|more price algorithms can be added, perhaps using average deviation,
| quartile prices, etc
|
|has a few quirks, id love to hear feedback with specific data and desired outcome
|
|"| foo" indicates commented out code
|" |foo" indicates a real comment
Sub Main
/declare slot int local
/declare dupecheck int local
/declare itemname string local
/declare result int local
/declare stddev int local
/declare itemsfound int local
/declare pricetotal int local
/declare avgprice int local
/declare minprice int local
/declare avgdev int local
/declare devhigh int local
/declare quartprice int local
/declare maxprice int local
/declare price int local
/declare fairprice int local
/declare targetprice int local
/declare newtargetprice int local
/declare PlatVal int local
|open the trader window
:OpenTraderAgain
/trader
/delay 1s ${Window[BazaarWnd].Open}
/if (!${Window[BazaarWnd].Open}) /goto :OpenTraderAgain
|open the bazaar search window
:OpenBazaarAgain
/bazaar
/delay 2s ${Window[BazaarSearchWnd].Open}
/if (!${Window[BazaarSearchWnd].Open}) /goto :OpenBazaarAgain
|update traders
/delay 1
/notify BazaarSearchWnd BZR_UpdatePlayerButton leftmouseup
/delay 2s
|loop through all 80 slots
/varset slot -1
:nextslot
/varcalc slot ${slot}+1
/if (${slot}>79) /goto :donewithslots
|click on the current slot
/notify BZW_BazaarSlotsWnd BZR_BazaarSlot${slot} leftmouseup
|skip the slot if its empty
/if (!${Window[BazaarWnd].Child[BZW_SetPrice_Button].Enabled}) /goto :nextslot
|skip the slot if it doesnt have a price
/if (!${Window[BazaarWnd].Child[BZW_Clear_Button].Enabled}) /goto :nextslot
|get the name of the item in the current slot
/varset itemname ${Window[BZW_BazaarSlotsWnd].Child[BZR_BazaarSlot${slot}].Tooltip}
|dont do the same item twice
/if (${slot}) {
/for dupecheck 0 to ${Math.Calc[${slot}-1]}
/if (${itemname.Equal[${Window[BZW_BazaarSlotsWnd].Child[BZR_BazaarSlot${dupecheck}].Tooltip}]}) /goto :nextslot
/next dupecheck
}
|search the bazaar for this item
:SearchBazaarAgain
/bzsrch race any class any stat any slot any type any price 0 9999999 ${itemname}
/delay 5s ${Bazaar.Done}
/if (!${Bazaar.Done}) /goto :SearchBazaarAgain
|skip this item if its not in /bazaar
/if (!${Bazaar.Count}) /goto :nextslot
|find average, min, max price
/varset itemsfound 0
/varset pricetotal 0
/varset minprice 9999999
/varset maxprice 0
/for result 1 to ${Bazaar.Count}
|make sure this is the right item
/if (${Bazaar.Item[${result}].Name.Equal[${itemname}]}&&!${Me.Name.Equal[${Bazaar.Item[${result}].Trader.Name}]}) {
/varcalc itemsfound ${itemsfound}+${Bazaar.Item[${result}].Quantity}
/varcalc pricetotal ${pricetotal}+${Bazaar.Item[${result}].Price}*${Bazaar.Item[${result}].Quantity}
/if (${Bazaar.Item[${result}].Price}<${minprice}) /varset minprice ${Bazaar.Item[${result}].Price}
/if (${Bazaar.Item[${result}].Price}>${maxprice}) /varset maxprice ${Bazaar.Item[${result}].Price}
}
/next result
|skip this item if its not in /bazaar
/if (!${itemsfound}) /goto :nextslot
/varset avgprice ${Math.Calc[${pricetotal}/${itemsfound}/1000].Int}
/varset minprice ${Math.Calc[${minprice}/1000].Int}
/varset maxprice ${Math.Calc[${maxprice}/1000].Int}
|find stddev and avgdev
/varset stddev 0
/varset avgdev 0
/for result 1 to ${Bazaar.Count}
/if (${Bazaar.Item[${result}].Name.Equal[${itemname}]}&&!${Me.Name.Equal[${Bazaar.Item[${result}].Trader.Name}]}) {
/varcalc stddev ${stddev}+((${Math.Calc[${Bazaar.Item[${result}].Price}/1000].Int}-${avgprice})^2)*${Bazaar.Item[${result}].Quantity}
/varcalc avgdev ${avgdev}+${Math.Abs[${Bazaar.Item[${result}].Price}-${avgprice}*1000]}*${Bazaar.Item[${result}].Quantity}
}
/next result
/varset stddev ${Math.Calc[(${stddev}/${itemsfound})^.5]}
/varset avgdev ${Math.Calc[${avgdev}/${itemsfound}/1000].Int}
| |find 'fair price', the lowest price below the first quartile
| |or 1pp below the lowest price if it IS the first quartile
| /varset quartcount 0
| /varset oldquartcount -1
| /varset price ${minprice}
| :fairpriceloop
| /if (${quartcount}>${oldquartcount}) /varset quartprice ${Math.Calc[${price}-1]}
| /varset oldquartcount ${quartcount}
| /for result 1 to ${Bazaar.Count}
| /if (${Bazaar.Item[${result}].Name.Equal[${itemname}]}&&!${Me.Name.Equal[${Bazaar.Item[${result}].Trader.Name}]}) {
| /if (${Math.Calc[${Bazaar.Item[${result}].Price}/1000].Int}==${price}) /varcalc quartcount ${quartcount}+${Bazaar.Item[${result}].Quantity}
| }
| /next result
| /varcalc price ${price}+1
| /if (${quartcount}<${Math.Calc[${itemsfound}/4]}&&${price}<=${avgprice}) /goto :fairpriceloop
|find 'fair price'
/varcalc quartprice (${avgprice}+${minprice})/2
/varset fairprice 9999999
/for result 1 to ${Bazaar.Count}
/if (${Bazaar.Item[${result}].Name.Equal[${itemname}]}&&!${Me.Name.Equal[${Bazaar.Item[${result}].Trader.Name}]}) {
/if (${Math.Calc[${Bazaar.Item[${result}].Price}/1000].Int}>=${quartprice}&&${Math.Calc[${Bazaar.Item[${result}].Price}/1000].Int}<${fairprice}) /varset fairprice ${Math.Calc[${Bazaar.Item[${result}].Price}/1000].Int}
}
/next result
|pick new price based on rarity, value, etc
/if (${itemsfound}<15) {
/varset targetprice ${Math.Calc[${avgprice}-${stddev}]}
/varset targetprice ${If[${targetprice}<${minprice},${minprice},${targetprice}]}
} else {
/varset targetprice ${fairprice}
}
/varcalc targetprice ${targetprice}-1
|check for underpriced item
/if (${targetprice}<${Math.Calc[${SelectedItem.Value}/1050]}) {
/echo Underpriced Goods! ${itemname} for ${minprice}pp value:${Math.Calc[${SelectedItem.Value}/1050]} etc:(${avgprice},${targetprice},${stddev},${itemsfound})
/varset targetprice ${Math.Calc[${SelectedItem.Value}/1000].Int}
}
|up the new price to 1pp below the next higher price
/varset newtargetprice 9999999
/for result 1 to ${Bazaar.Count}
/if (${Bazaar.Item[${result}].Name.Equal[${itemname}]}&&!${Me.Name.Equal[${Bazaar.Item[${result}].Trader.Name}]}) {
/if (${Math.Calc[${Bazaar.Item[${result}].Price}/1000].Int}>${targetprice}&&${Math.Calc[${Bazaar.Item[${result}].Price}/1000].Int}<${newtargetprice}) /varset newtargetprice ${Math.Calc[${Bazaar.Item[${result}].Price}/1000].Int}
}
/next result
/if (${newtargetprice}>1000) {
/varcalc targetprice ${newtargetprice}-100
} else {
/varcalc targetprice ${newtargetprice}-5
}
|set new price in pp, only lamers use small coins in /trader
/if (${targetprice}<${Window[BazaarWnd].Child[BZW_Money0].Text}) {
/echo repricing ${itemname} from ${Window[BazaarWnd].Child[BZW_Money0].Text} to ${targetprice}
:openqtywndagain
/notify BazaarWnd BZW_Money0 leftmouseup
/delay 2s
/if (!${Window[QuantityWnd].Open}) /goto :openqtywndagain
/delay 1
/for PlatVal 1 to ${String[${Window[BazaarWnd].Child[BZW_Money0].Text}].Length}
/keypress backspace chat
/next PlatVal
/for PlatVal 1 to ${Int[${String[${targetprice}].Length}]}
/keypress ${Int[${String[${targetprice}].Mid[${PlatVal},1]}]} chat
/next PlatVal
/notify QuantityWnd QTYW_Accept_Button leftmouseup
/delay 1
/notify BazaarWnd BZW_SetPrice_Button leftmouseup
/delay 1
}
/goto :nextslot
:donewithslots
/return
Sub NullSub
/return

I had the same thing happen for black chipped marbles. In my particular case, the price I was driven to was below the vendor value. It reset my price to 10000000p and also gave the low value warning echo. I then looked on the bazaar lookup for the people that drove the price that low, went and bought their gems, took them to the vendor and made close to 500p in 10 min. I was laughing all the way.Very odd.... I just had this price a black pearl for 1000000p. Now, I'm amenable to the profit, but it seemed odd :-) Looking at what was for sale in the bazaar at that time, searching on black pearl, there were plenty of items with that as part of their name, but only 1 other seller with a black pearl for sale -- for 10p. Nothing about any of the other items seemed out of the ordinary. Just something to note.

