Function bodies 1,118 total
GetBollingerPosition function · go · L214-L225 (12 LOC)cmd/volume-gen/mean_reversion.go
func GetBollingerPosition(price float64, bands BollingerBands) string {
if price > bands.Upper {
return "above_upper"
} else if price < bands.Lower {
return "below_lower"
} else if price > bands.Middle {
return "upper_half"
} else if price < bands.Middle {
return "lower_half"
}
return "at_middle"
}CalculateRSI function · go · L235-L266 (32 LOC)cmd/volume-gen/mean_reversion.go
func CalculateRSI(prices []PricePoint, period int) float64 {
if len(prices) < period+1 {
return 50.0 // Neutral if not enough data
}
// Calculate price changes
gains := 0.0
losses := 0.0
startIdx := len(prices) - period - 1
for i := startIdx + 1; i < len(prices); i++ {
change := prices[i].Price - prices[i-1].Price
if change > 0 {
gains += change
} else {
losses += math.Abs(change)
}
}
// Calculate average gain and loss
avgGain := gains / float64(period)
avgLoss := losses / float64(period)
if avgLoss == 0 {
return 100.0
}
rs := avgGain / avgLoss
rsi := 100.0 - (100.0 / (1.0 + rs))
return rsi
}GetRSISignal function · go · L269-L280 (12 LOC)cmd/volume-gen/mean_reversion.go
func GetRSISignal(rsi float64) string {
if rsi > 70 {
return "overbought"
} else if rsi < 30 {
return "oversold"
} else if rsi > 55 {
return "bullish"
} else if rsi < 45 {
return "bearish"
}
return "neutral"
}GetCombinedSignal method · go · L294-L328 (35 LOC)cmd/volume-gen/mean_reversion.go
func (mrc *MeanReversionCalculator) GetCombinedSignal(
priceHistory *PriceHistory,
) CombinedSignal {
signal := CombinedSignal{}
// Get current price and SMA
currentPrice := priceHistory.GetCurrentPrice()
sma := priceHistory.GetSMA(mrc.config.SMAPeriod)
// Calculate buy bias
signal.BuyBias = mrc.CalculateBuyBias(currentPrice, sma)
signal.Strength = mrc.GetReversionStrength(currentPrice, sma)
signal.Condition = mrc.GetMarketCondition(currentPrice, sma)
// Calculate RSI if enough data
if priceHistory.Size() >= 14 {
signal.RSI = CalculateRSI(priceHistory.prices, 14)
signal.RSISignal = GetRSISignal(signal.RSI)
}
// Determine overall recommendation
if signal.BuyBias > 15 && signal.RSISignal == "oversold" {
signal.Recommendation = "strong_buy"
} else if signal.BuyBias > 5 {
signal.Recommendation = "buy"
} else if signal.BuyBias < -15 && signal.RSISignal == "overbought" {
signal.Recommendation = "strong_sell"
} else if signal.BuyBias < -5 {
signal.RecommendatiNewPriceHistory function · go · L23-L33 (11 LOC)cmd/volume-gen/price_history.go
func NewPriceHistory(chainID uint64, maxSize int) *PriceHistory {
if maxSize < 2 {
maxSize = 20 // Minimum for meaningful analysis
}
return &PriceHistory{
chainID: chainID,
prices: make([]PricePoint, 0, maxSize),
maxSize: maxSize,
}
}AddPrice method · go · L36-L50 (15 LOC)cmd/volume-gen/price_history.go
func (ph *PriceHistory) AddPrice(price float64, timestamp time.Time) {
ph.mu.Lock()
defer ph.mu.Unlock()
// Add new price point
ph.prices = append(ph.prices, PricePoint{
Timestamp: timestamp,
Price: price,
})
// Keep only the last maxSize points
if len(ph.prices) > ph.maxSize {
ph.prices = ph.prices[len(ph.prices)-ph.maxSize:]
}
}GetSMA method · go · L53-L75 (23 LOC)cmd/volume-gen/price_history.go
func (ph *PriceHistory) GetSMA(periods int) float64 {
ph.mu.RLock()
defer ph.mu.RUnlock()
if len(ph.prices) == 0 {
return 0
}
// If not enough data, use what we have
if periods > len(ph.prices) {
periods = len(ph.prices)
}
// Calculate average of last N periods
sum := 0.0
startIdx := len(ph.prices) - periods
for i := startIdx; i < len(ph.prices); i++ {
sum += ph.prices[i].Price
}
return sum / float64(periods)
}Same scanner, your repo: https://repobility.com — Repobility
GetEMA method · go · L78-L104 (27 LOC)cmd/volume-gen/price_history.go
func (ph *PriceHistory) GetEMA(periods int) float64 {
ph.mu.RLock()
defer ph.mu.RUnlock()
if len(ph.prices) == 0 {
return 0
}
// If not enough data, fall back to SMA
if len(ph.prices) < periods {
sum := 0.0
for _, p := range ph.prices {
sum += p.Price
}
return sum / float64(len(ph.prices))
}
// EMA calculation
multiplier := 2.0 / float64(periods+1)
ema := ph.prices[len(ph.prices)-periods].Price // Start with first price in period
for i := len(ph.prices) - periods + 1; i < len(ph.prices); i++ {
ema = (ph.prices[i].Price * multiplier) + (ema * (1 - multiplier))
}
return ema
}GetCurrentPrice method · go · L107-L116 (10 LOC)cmd/volume-gen/price_history.go
func (ph *PriceHistory) GetCurrentPrice() float64 {
ph.mu.RLock()
defer ph.mu.RUnlock()
if len(ph.prices) == 0 {
return 0
}
return ph.prices[len(ph.prices)-1].Price
}GetPriceChange method · go · L119-L139 (21 LOC)cmd/volume-gen/price_history.go
func (ph *PriceHistory) GetPriceChange(periods int) float64 {
ph.mu.RLock()
defer ph.mu.RUnlock()
if len(ph.prices) < 2 {
return 0
}
if periods > len(ph.prices) {
periods = len(ph.prices)
}
oldPrice := ph.prices[len(ph.prices)-periods].Price
currentPrice := ph.prices[len(ph.prices)-1].Price
if oldPrice == 0 {
return 0
}
return ((currentPrice - oldPrice) / oldPrice) * 100
}GetVolatility method · go · L142-L186 (45 LOC)cmd/volume-gen/price_history.go
func (ph *PriceHistory) GetVolatility(periods int) float64 {
ph.mu.RLock()
defer ph.mu.RUnlock()
if len(ph.prices) < 2 {
return 0
}
if periods > len(ph.prices) {
periods = len(ph.prices)
}
// Calculate returns (percentage changes)
returns := make([]float64, 0, periods-1)
startIdx := len(ph.prices) - periods
for i := startIdx + 1; i < len(ph.prices); i++ {
if ph.prices[i-1].Price > 0 {
ret := (ph.prices[i].Price - ph.prices[i-1].Price) / ph.prices[i-1].Price
returns = append(returns, ret)
}
}
if len(returns) == 0 {
return 0
}
// Calculate mean return
meanReturn := 0.0
for _, r := range returns {
meanReturn += r
}
meanReturn /= float64(len(returns))
// Calculate variance
variance := 0.0
for _, r := range returns {
diff := r - meanReturn
variance += diff * diff
}
variance /= float64(len(returns))
// Return standard deviation as percentage
return (variance * variance) * 100
}GetTrend method · go · L189-L207 (19 LOC)cmd/volume-gen/price_history.go
func (ph *PriceHistory) GetTrend(shortPeriod, longPeriod int) string {
ph.mu.RLock()
defer ph.mu.RUnlock()
if len(ph.prices) < longPeriod {
return "insufficient_data"
}
shortMA := ph.getSMAUnsafe(shortPeriod)
longMA := ph.getSMAUnsafe(longPeriod)
if shortMA > longMA*1.05 {
return "uptrend"
} else if shortMA < longMA*0.95 {
return "downtrend"
}
return "sideways"
}getSMAUnsafe method · go · L210-L227 (18 LOC)cmd/volume-gen/price_history.go
func (ph *PriceHistory) getSMAUnsafe(periods int) float64 {
if len(ph.prices) == 0 {
return 0
}
if periods > len(ph.prices) {
periods = len(ph.prices)
}
sum := 0.0
startIdx := len(ph.prices) - periods
for i := startIdx; i < len(ph.prices); i++ {
sum += ph.prices[i].Price
}
return sum / float64(periods)
}IsPriceExtreme method · go · L230-L254 (25 LOC)cmd/volume-gen/price_history.go
func (ph *PriceHistory) IsPriceExtreme(smaPeriods int, threshold float64) (bool, string) {
ph.mu.RLock()
defer ph.mu.RUnlock()
if len(ph.prices) < smaPeriods {
return false, "insufficient_data"
}
currentPrice := ph.prices[len(ph.prices)-1].Price
sma := ph.getSMAUnsafe(smaPeriods)
if sma == 0 {
return false, "zero_sma"
}
deviation := (currentPrice - sma) / sma
if deviation > threshold {
return true, "overbought"
} else if deviation < -threshold {
return true, "oversold"
}
return false, "normal"
}GetPriceStats method · go · L268-L305 (38 LOC)cmd/volume-gen/price_history.go
func (ph *PriceHistory) GetPriceStats() PriceStats {
ph.mu.RLock()
defer ph.mu.RUnlock()
stats := PriceStats{
Trend: "insufficient_data",
}
if len(ph.prices) == 0 {
return stats
}
stats.CurrentPrice = ph.prices[len(ph.prices)-1].Price
if len(ph.prices) >= 20 {
stats.SMA20 = ph.getSMAUnsafe(20)
stats.EMA20 = ph.getEMAUnsafe(20)
stats.Trend = ph.getTrendUnsafe(5, 20)
if stats.SMA20 > 0 {
deviation := (stats.CurrentPrice - stats.SMA20) / stats.SMA20
if deviation > 0.15 {
stats.IsExtreme = true
stats.ExtremeStatus = "overbought"
} else if deviation < -0.15 {
stats.IsExtreme = true
stats.ExtremeStatus = "oversold"
}
}
}
if len(ph.prices) >= 24 {
stats.Change24h = ph.getPriceChangeUnsafe(24)
stats.Volatility = ph.getVolatilityUnsafe(24)
}
return stats
}Citation: Repobility (2026). State of AI-Generated Code. https://repobility.com/research/
getEMAUnsafe method · go · L308-L321 (14 LOC)cmd/volume-gen/price_history.go
func (ph *PriceHistory) getEMAUnsafe(periods int) float64 {
if len(ph.prices) < periods {
return ph.getSMAUnsafe(len(ph.prices))
}
multiplier := 2.0 / float64(periods+1)
ema := ph.prices[len(ph.prices)-periods].Price
for i := len(ph.prices) - periods + 1; i < len(ph.prices); i++ {
ema = (ph.prices[i].Price * multiplier) + (ema * (1 - multiplier))
}
return ema
}getPriceChangeUnsafe method · go · L323-L336 (14 LOC)cmd/volume-gen/price_history.go
func (ph *PriceHistory) getPriceChangeUnsafe(periods int) float64 {
if len(ph.prices) < 2 || periods > len(ph.prices) {
return 0
}
oldPrice := ph.prices[len(ph.prices)-periods].Price
currentPrice := ph.prices[len(ph.prices)-1].Price
if oldPrice == 0 {
return 0
}
return ((currentPrice - oldPrice) / oldPrice) * 100
}getVolatilityUnsafe method · go · L338-L371 (34 LOC)cmd/volume-gen/price_history.go
func (ph *PriceHistory) getVolatilityUnsafe(periods int) float64 {
if len(ph.prices) < 2 || periods > len(ph.prices) {
return 0
}
returns := make([]float64, 0, periods-1)
startIdx := len(ph.prices) - periods
for i := startIdx + 1; i < len(ph.prices); i++ {
if ph.prices[i-1].Price > 0 {
ret := (ph.prices[i].Price - ph.prices[i-1].Price) / ph.prices[i-1].Price
returns = append(returns, ret)
}
}
if len(returns) == 0 {
return 0
}
meanReturn := 0.0
for _, r := range returns {
meanReturn += r
}
meanReturn /= float64(len(returns))
variance := 0.0
for _, r := range returns {
diff := r - meanReturn
variance += diff * diff
}
variance /= float64(len(returns))
return (variance * variance) * 100
}getTrendUnsafe method · go · L373-L388 (16 LOC)cmd/volume-gen/price_history.go
func (ph *PriceHistory) getTrendUnsafe(shortPeriod, longPeriod int) string {
if len(ph.prices) < longPeriod {
return "insufficient_data"
}
shortMA := ph.getSMAUnsafe(shortPeriod)
longMA := ph.getSMAUnsafe(longPeriod)
if shortMA > longMA*1.05 {
return "uptrend"
} else if shortMA < longMA*0.95 {
return "downtrend"
}
return "sideways"
}Size method · go · L391-L395 (5 LOC)cmd/volume-gen/price_history.go
func (ph *PriceHistory) Size() int {
ph.mu.RLock()
defer ph.mu.RUnlock()
return len(ph.prices)
}Clear method · go · L398-L402 (5 LOC)cmd/volume-gen/price_history.go
func (ph *PriceHistory) Clear() {
ph.mu.Lock()
defer ph.mu.Unlock()
ph.prices = make([]PricePoint, 0, ph.maxSize)
}DefaultTimePatternConfig function · go · L19-L27 (9 LOC)cmd/volume-gen/time_patterns.go
func DefaultTimePatternConfig() TimePatternConfig {
return TimePatternConfig{
BaseInterval: 30 * time.Second,
ClusteringEnabled: true,
BurstIntensity: 3.0, // Average 3 trades per burst
QuietPeriodProb: 0.2, // 20% chance of quiet period
QuietPeriodMult: 3.0, // 3x slower during quiet
}
}NewTimePatternGenerator function · go · L38-L44 (7 LOC)cmd/volume-gen/time_patterns.go
func NewTimePatternGenerator(config TimePatternConfig, rng *rand.Rand) *TimePatternGenerator {
return &TimePatternGenerator{
config: config,
rng: rng,
inQuietPeriod: false,
}
}Repobility — the code-quality scanner for AI-generated software · https://repobility.com
NextTradeDelay method · go · L47-L68 (22 LOC)cmd/volume-gen/time_patterns.go
func (tpg *TimePatternGenerator) NextTradeDelay() time.Duration {
now := time.Now()
// Check if we're in a quiet period
if tpg.inQuietPeriod {
if now.After(tpg.quietEndTime) {
tpg.inQuietPeriod = false
} else {
// In quiet period: longer delays
return tpg.exponentialDelay(tpg.config.BaseInterval, tpg.config.QuietPeriodMult)
}
}
// Randomly enter quiet period
if tpg.config.QuietPeriodProb > 0 && tpg.rng.Float64() < tpg.config.QuietPeriodProb {
tpg.enterQuietPeriod()
return tpg.exponentialDelay(tpg.config.BaseInterval, tpg.config.QuietPeriodMult)
}
// Normal period: use exponential distribution for natural clustering
return tpg.exponentialDelay(tpg.config.BaseInterval, 1.0)
}exponentialDelay method · go · L71-L99 (29 LOC)cmd/volume-gen/time_patterns.go
func (tpg *TimePatternGenerator) exponentialDelay(mean time.Duration, multiplier float64) time.Duration {
if !tpg.config.ClusteringEnabled {
// If clustering disabled, return fixed interval with small jitter
jitter := (tpg.rng.Float64() - 0.5) * 0.2 // ±10% jitter
return time.Duration(float64(mean) * (1.0 + jitter) * multiplier)
}
// Exponential distribution: -ln(U) * mean
u := tpg.rng.Float64()
if u == 0 {
u = 0.0001 // Avoid log(0)
}
delay := -math.Log(u) * float64(mean) * multiplier
// Cap at reasonable maximum (10x mean)
maxDelay := float64(mean) * 10.0 * multiplier
if delay > maxDelay {
delay = maxDelay
}
// Minimum delay (0.1x mean)
minDelay := float64(mean) * 0.1 * multiplier
if delay < minDelay {
delay = minDelay
}
return time.Duration(delay)
}enterQuietPeriod method · go · L102-L107 (6 LOC)cmd/volume-gen/time_patterns.go
func (tpg *TimePatternGenerator) enterQuietPeriod() {
// Quiet period lasts 2-10 minutes
duration := time.Duration(120+tpg.rng.Intn(480)) * time.Second
tpg.quietEndTime = time.Now().Add(duration)
tpg.inQuietPeriod = true
}GetTradesInBurst method · go · L110-L125 (16 LOC)cmd/volume-gen/time_patterns.go
func (tpg *TimePatternGenerator) GetTradesInBurst() int {
if !tpg.config.ClusteringEnabled || tpg.inQuietPeriod {
return 1 // Single trade if not clustering or in quiet period
}
// Use Poisson distribution for burst size
count := PoissonCount(tpg.config.BurstIntensity, tpg.rng)
if count < 1 {
count = 1
}
if count > 10 {
count = 10 // Cap burst size
}
return count
}IsInQuietPeriod method · go · L128-L139 (12 LOC)cmd/volume-gen/time_patterns.go
func (tpg *TimePatternGenerator) IsInQuietPeriod() bool {
if !tpg.inQuietPeriod {
return false
}
if time.Now().After(tpg.quietEndTime) {
tpg.inQuietPeriod = false
return false
}
return true
}GetCurrentIntensity method · go · L143-L150 (8 LOC)cmd/volume-gen/time_patterns.go
func (tpg *TimePatternGenerator) GetCurrentIntensity() float64 {
if tpg.inQuietPeriod {
return 1.0 / tpg.config.QuietPeriodMult
}
// Higher burst intensity = higher current intensity
return tpg.config.BurstIntensity / 3.0 // Normalize around 1.0
}GenerateTradeTimingStrategy method · go · L161-L182 (22 LOC)cmd/volume-gen/time_patterns.go
func (tpg *TimePatternGenerator) GenerateTradeTimingStrategy() TradeTimingStrategy {
// Calculate when next trade event occurs
delay := tpg.NextTradeDelay()
nextTime := time.Now().Add(delay)
// Determine burst size
burstSize := tpg.GetTradesInBurst()
// If burst, trades are spread over shorter intervals
var burstInterval time.Duration
if burstSize > 1 {
// Burst trades happen quickly (5-30 seconds apart)
burstInterval = time.Duration(5+tpg.rng.Intn(25)) * time.Second
}
return TradeTimingStrategy{
NextTradeTime: nextTime,
TradesInBurst: burstSize,
TradesRemaining: burstSize,
BurstInterval: burstInterval,
}
}DefaultTimeOfDayPattern function · go · L194-L202 (9 LOC)cmd/volume-gen/time_patterns.go
func DefaultTimeOfDayPattern() TimeOfDayPattern {
return TimeOfDayPattern{
Enabled: true,
PeakHours: []int{9, 10, 11, 13, 14, 15}, // Business hours EST/PST
QuietHours: []int{1, 2, 3, 4, 5}, // Late night EST
PeakBoost: 1.3,
QuietPenalty: 0.7,
}
}All rows scored by the Repobility analyzer (https://repobility.com)
GetTimeOfDayMultiplier method · go · L205-L227 (23 LOC)cmd/volume-gen/time_patterns.go
func (tod *TimeOfDayPattern) GetTimeOfDayMultiplier() float64 {
if !tod.Enabled {
return 1.0
}
currentHour := time.Now().UTC().Hour()
// Check if peak hour
for _, hour := range tod.PeakHours {
if currentHour == hour {
return tod.PeakBoost
}
}
// Check if quiet hour
for _, hour := range tod.QuietHours {
if currentHour == hour {
return tod.QuietPenalty
}
}
return 1.0 // Normal hours
}DefaultDayOfWeekPattern function · go · L236-L241 (6 LOC)cmd/volume-gen/time_patterns.go
func DefaultDayOfWeekPattern() DayOfWeekPattern {
return DayOfWeekPattern{
Enabled: true,
WeekendMultiplier: 0.8, // 20% less activity on weekends
}
}GetDayOfWeekMultiplier method · go · L244-L255 (12 LOC)cmd/volume-gen/time_patterns.go
func (dow *DayOfWeekPattern) GetDayOfWeekMultiplier() float64 {
if !dow.Enabled {
return 1.0
}
weekday := time.Now().Weekday()
if weekday == time.Saturday || weekday == time.Sunday {
return dow.WeekendMultiplier
}
return 1.0
}NewCombinedTimingEngine function · go · L266-L277 (12 LOC)cmd/volume-gen/time_patterns.go
func NewCombinedTimingEngine(
config TimePatternConfig,
rng *rand.Rand,
phaseManager *MarketCycleManager,
) *CombinedTimingEngine {
return &CombinedTimingEngine{
patternGen: NewTimePatternGenerator(config, rng),
timeOfDay: DefaultTimeOfDayPattern(),
dayOfWeek: DefaultDayOfWeekPattern(),
phaseManager: phaseManager,
}
}GetNextTradeDelay method · go · L280-L303 (24 LOC)cmd/volume-gen/time_patterns.go
func (cte *CombinedTimingEngine) GetNextTradeDelay() time.Duration {
// Base delay from pattern generator
baseDelay := cte.patternGen.NextTradeDelay()
// Apply time-based multipliers
todMultiplier := cte.timeOfDay.GetTimeOfDayMultiplier()
dowMultiplier := cte.dayOfWeek.GetDayOfWeekMultiplier()
// Apply market phase volume multiplier
phaseMultiplier := 1.0
if cte.phaseManager != nil {
phaseVolume := cte.phaseManager.GetVolumeMultiplier()
// Convert volume multiplier to time multiplier (inverse)
phaseMultiplier = 1.0 / phaseVolume
}
// Combine multipliers (multiplicative)
totalMultiplier := todMultiplier * dowMultiplier * phaseMultiplier
// Apply combined multiplier to delay
adjustedDelay := time.Duration(float64(baseDelay) * totalMultiplier)
return adjustedDelay
}GetTradesInBurst method · go · L306-L331 (26 LOC)cmd/volume-gen/time_patterns.go
func (cte *CombinedTimingEngine) GetTradesInBurst() int {
baseBurst := cte.patternGen.GetTradesInBurst()
// During peak hours, bursts can be larger
todMultiplier := cte.timeOfDay.GetTimeOfDayMultiplier()
if todMultiplier > 1.0 && baseBurst > 1 {
// Chance to add 1-2 more trades during peaks
if cte.patternGen.rng.Float64() < 0.3 {
baseBurst += 1 + cte.patternGen.rng.Intn(2)
}
}
// During quiet hours, reduce burst size
if todMultiplier < 1.0 && baseBurst > 2 {
baseBurst = baseBurst - 1
}
if baseBurst < 1 {
baseBurst = 1
}
if baseBurst > 10 {
baseBurst = 10
}
return baseBurst
}GetCurrentActivityLevel method · go · L334-L345 (12 LOC)cmd/volume-gen/time_patterns.go
func (cte *CombinedTimingEngine) GetCurrentActivityLevel() float64 {
baseIntensity := cte.patternGen.GetCurrentIntensity()
todMult := cte.timeOfDay.GetTimeOfDayMultiplier()
dowMult := cte.dayOfWeek.GetDayOfWeekMultiplier()
phaseMult := 1.0
if cte.phaseManager != nil {
phaseMult = cte.phaseManager.GetVolumeMultiplier()
}
return baseIntensity * todMult * dowMult * phaseMult
}GetActivityDescription method · go · L348-L362 (15 LOC)cmd/volume-gen/time_patterns.go
func (cte *CombinedTimingEngine) GetActivityDescription() string {
level := cte.GetCurrentActivityLevel()
if level < 0.3 {
return "very_quiet"
} else if level < 0.7 {
return "quiet"
} else if level < 1.3 {
return "normal"
} else if level < 1.8 {
return "active"
}
return "very_active"
}Same scanner, your repo: https://repobility.com — Repobility
String method · go · L18-L31 (14 LOC)cmd/volume-gen/user_archetypes.go
func (a UserArchetype) String() string {
switch a {
case ArchetypeWhale:
return "Whale"
case ArchetypeDayTrader:
return "DayTrader"
case ArchetypeHodler:
return "Hodler"
case ArchetypeRetail:
return "Retail"
default:
return "Unknown"
}
}CreateUserProfiles function · go · L111-L162 (52 LOC)cmd/volume-gen/user_archetypes.go
func CreateUserProfiles(numUsers int, rng *rand.Rand) []UserProfile {
profiles := make([]UserProfile, numUsers)
// Calculate archetype distribution
archetypeCounts := make(map[UserArchetype]int)
remaining := numUsers
for i, config := range ArchetypeConfigs {
var count int
if i == len(ArchetypeConfigs)-1 {
// Last archetype gets remaining users
count = remaining
} else {
count = int(float64(numUsers) * config.Population)
remaining -= count
}
archetypeCounts[config.Archetype] = count
}
// Assign users to archetypes
userIdx := 0
for _, config := range ArchetypeConfigs {
count := archetypeCounts[config.Archetype]
for i := 0; i < count; i++ {
// Add some randomness to behavior within archetype
buyProb := config.BuyProbability + (rng.Float64()-0.5)*0.1
tradeFreq := config.TradeFrequency * (0.8 + rng.Float64()*0.4)
// Clamp values
if buyProb < 0.1 {
buyProb = 0.1
}
if buyProb > 0.9 {
buyProb = 0.9
}
profiles[userIdx] ShouldTrade method · go · L165-L174 (10 LOC)cmd/volume-gen/user_archetypes.go
func (u *UserProfile) ShouldTrade(baseInterval float64, rng *rand.Rand) bool {
// Higher frequency = more likely to trade
probability := u.TradeFrequency * (1.0 / baseInterval) * 100
if probability > 100 {
probability = 100
}
return rng.Float64()*100 < probability
}DecideBuyOrSell method · go · L177-L243 (67 LOC)cmd/volume-gen/user_archetypes.go
func (u *UserProfile) DecideBuyOrSell(
currentPrice float64,
movingAverage float64,
marketPhase MarketPhase,
rng *rand.Rand,
) bool {
baseBuyProb := u.BuyProbability * 100
// Adjust based on market phase
switch marketPhase {
case PhaseAccumulation:
// Contrarian: buy when price is low
if currentPrice < movingAverage*0.95 {
baseBuyProb += 10
}
case PhaseMarkup:
// Momentum: follow the trend up
if currentPrice > movingAverage*1.05 {
baseBuyProb += 5
}
case PhaseDistribution:
// Smart money exits: more selling
baseBuyProb -= 15
case PhaseMarkdown:
// Panic: more selling
baseBuyProb -= 20
}
// Archetype-specific adjustments
switch u.Archetype {
case ArchetypeWhale:
// Whales are contrarian
if currentPrice > movingAverage*1.2 {
baseBuyProb -= 20 // Sell high
} else if currentPrice < movingAverage*0.8 {
baseBuyProb += 20 // Buy low
}
case ArchetypeDayTrader:
// Day traders follow momentum
priceChange := (currentPrice - movingAGetTradeSize method · go · L246-L249 (4 LOC)cmd/volume-gen/user_archetypes.go
func (u *UserProfile) GetTradeSize(intensityMultiplier float64, rng *rand.Rand) float64 {
baseSize := GenerateTradeSize(u.Archetype, rng)
return baseSize * intensityMultiplier
}ShouldWaitForBetterPrice method · go · L252-L265 (14 LOC)cmd/volume-gen/user_archetypes.go
func (u *UserProfile) ShouldWaitForBetterPrice(
priceImpact float64,
rng *rand.Rand,
) bool {
// If price impact is high and user is patient, might skip
impactThreshold := (1.0 - u.PatientScore) * 10.0 // 0-10% depending on patience
if priceImpact > impactThreshold {
// Roll against patience score
return rng.Float64() < u.PatientScore
}
return false
}GetArchetypeConfig function · go · L268-L275 (8 LOC)cmd/volume-gen/user_archetypes.go
func GetArchetypeConfig(archetype UserArchetype) ArchetypeConfig {
for _, config := range ArchetypeConfigs {
if config.Archetype == archetype {
return config
}
}
return ArchetypeConfigs[3] // Default to Retail
}DefaultConfig function · go · L100-L112 (13 LOC)cmd/volume-gen/worker.go
func DefaultConfig() Config {
return Config{
Interval: 30 * time.Second,
NumFakeUsers: 10,
EnableMarketPhases: true,
PhaseDuration: 7 * 24 * time.Hour,
MeanReversionConfig: DefaultMeanReversionConfig(),
TimePatternConfig: DefaultTimePatternConfig(),
EnableUserArchetypes: true,
EnableTimeOfDay: true,
EnableDayOfWeek: true,
}
}Citation: Repobility (2026). State of AI-Generated Code. https://repobility.com/research/
NewWorker function · go · L115-L168 (54 LOC)cmd/volume-gen/worker.go
func NewWorker(
chainRepo ChainStatusLister,
poolRepo PoolReader,
userRepo UserLookup,
orderProcessor *virtualpool.OrderService,
grad *graduator.Graduator,
config Config,
) *Worker {
// Set defaults
if config.Interval == 0 {
config.Interval = 30 * time.Second
}
if config.NumFakeUsers == 0 {
config.NumFakeUsers = 10
}
// Initialize random number generator with seed
rng := mrand.New(mrand.NewSource(time.Now().UnixNano()))
// Create user profiles with archetypes
var userProfiles []UserProfile
if config.EnableUserArchetypes {
userProfiles = CreateUserProfiles(config.NumFakeUsers, rng)
} else {
// Create simple profiles without archetypes
userProfiles = make([]UserProfile, config.NumFakeUsers)
for i := 0; i < config.NumFakeUsers; i++ {
userProfiles[i] = UserProfile{
UserID: i + 1,
Address: fmt.Sprintf("0xfake%036d", i+1),
Archetype: ArchetypeRetail, // Default to retail
BuyProbability: 0.50, // Neutral
TradStart method · go · L171-L199 (29 LOC)cmd/volume-gen/worker.go
func (w *Worker) Start() error {
log.Printf("[FakeVolume Worker] Starting fake volume generation (interval: %v)", w.config.Interval)
log.Printf("[FakeVolume Worker] Features: MarketPhases=%v, MeanReversion=%v, TimeClustering=%v, UserArchetypes=%v",
w.config.EnableMarketPhases, w.config.MeanReversionConfig.Enabled,
w.config.TimePatternConfig.ClusteringEnabled, w.config.EnableUserArchetypes)
// Initialize fake user pool on startup
if err := w.initializeFakeUsers(); err != nil {
return fmt.Errorf("failed to initialize fake users: %w", err)
}
// Generate historical data if requested
if w.config.GenerateHistorical {
log.Println("[FakeVolume Worker] Generating one year of historical data...")
if err := w.generateHistoricalData(); err != nil {
return fmt.Errorf("failed to generate historical data: %w", err)
}
log.Println("[FakeVolume Worker] Historical data generation complete")
}
// Check each active chain and fill in historical data if needed
if err := w.checkAStop method · go · L202-L215 (14 LOC)cmd/volume-gen/worker.go
func (w *Worker) Stop() error {
log.Println("[FakeVolume Worker] Stopping...")
close(w.stopChan)
// Wait for worker to finish current operation
select {
case <-w.done:
log.Println("[FakeVolume Worker] Stopped")
case <-time.After(10 * time.Second):
log.Println("[FakeVolume Worker] Stop timeout")
}
return nil
}