Page 1 of 2 12 LastLast
Results 1 to 25 of 47

Thread: How to Dominate the Grand Exchange

  1. #1
    Join Date
    Feb 2007
    Location
    Alberta, Canada
    Posts
    4,615
    Mentioned
    50 Post(s)
    Quoted
    429 Post(s)

    Default How to Dominate the Grand Exchange

    How to Dominate the Grand Exchange
    Part 1 – The Basics
    Updated: April 3, 2015

    I have noticed that not many resources are publicly available to help people make money off the GE. In this tutorial, I hope to give you a general idea of how the RS3 Grand Exchange operates and how you can make money from it. The ideas that I discuss all directly relate to how the stock market works in real life, so this tutorial can give you some insight into stock investment as well. The information contained in this tutorial is not unique or secret and is gathered from various other sources.

    In this first part of How to Dominate the Grand Exchange, I’ll lay out the basics of how the GE works, how to invest in items, and a few methods for finding good items to invest in. I’ll also explain the basics of item flipping and how to make money doing that.

    Thank you to The Mayor because I stole his tutorial thread layout.
    Also thank you to @slacky, I would have never accomplished my MerchantAid script without his help, patience, code, and associated help. Derivatives of his code are found throughout my work, and I'd like to make a sweeping general credit because of that.

    This tutorial is broken down into four main sections:

    1. Grand Exchange Basics
    1. Market Pricing
    2. Trade Offers
    3. Making the Transaction
    4. Trade Limits
    5. GE Updates
    2. Grand Exchange Investing
    1. Introduction
    2. Trends
    3. Support and Resistance
    4. Choosing Items
    5. Investing Tips
    6. Advanced Support and Resistance
    3. Advanced Graph Trends
    1. Item Flipping
    2. Introduction to Item Flipping
    3. Finding an Item
    4. How to Determine Profit
    5. Performing the Flip
    6. Flipping Tips
    4. Technical Analysis (Part 2)
    1. Introduction to Technical Analysis
    2. How to Manage Data
    3. Methods
    4. How to Follow These Sections
    5. Moving Averages
    6. RSI
    7. Aroon Indicators
    8. Stochastic Oscillators
    9. Bollinger Bands




    Grand Exchange Basics

    For many people, the Grand Exchange is simply a spot where they can dump their items after a long day of botting, or where they’ll gather their supplies before a long run of processing. I see many people who pretend the pricing works like magic which can be manipulated by sheer will power. Hopefully after a little reading you’ll have a much better idea of how pricing works in the Grand Exchange, and you’ll be 1 step closer to utter domination and piles of gold.

    Market Pricing

    Like many people, I hadn’t thought about what “market price” really meant until I became interested in merchanting as a money making method. When you see the term “Market Price” what you are actually seeing is the average price for the previous day’s trades. The value is simply there to give you a guideline on what was actually paid for the item over the previous 24 hours. It’s very important to keep this in mind as we move through the more complicated ideas for money making. The market price is a guideline to show you roughly what the item is valued at. There may be wiggle room to allow you to squeeze more profit out of your items if you know what you’re doing.

    So how does pricing actually work then? It works the same as in real life: supply and demand. When there is more demand than supply, buyers will have trouble buying items and will raise their offers. If there is more supply than demand, suppliers will have trouble selling their items and will lower their prices in an attempt to sell them. In either case, the change in offer prices will show in the next day’s “Market Price” to indicate what fair price the suppliers were able to get for their items.

    Trade Offers

    When I say “Trade Offer” I mean either a buy or sell offer on the Grand Exchange. The moment you press “confirm” in an attempt to buy or sell is the moment that you are making an offer. The Grand Exchange prioritizes trade offers in the following way:

    1. The best deal available
    2. If multiple offers are for the same price, a queue system fills the oldest offer first

    What does this mean for you? It means that when you make an offer “Buy 100 Coal for 200gp each” you are actually saying “Buy 100 Coal for 200gp or less each”. Everyone who uses the Grand Exchange sees this happen when you get your items and some coins back after a purchase. The same goes with selling; you are offering Coal for 200gp or more, accepting extra profit if someone is willing to pay for it.


    Keep in mind when making your offers that actual prices will fluctuate heavily depending on the time of day. To make it simple, assume that the bulk of trading is done when North America is enjoying their evenings. Daytime in NA is when most trading happens, with night time having much less trading activity.

    Making the Transaction

    A concept not many people consider is how a transaction is actually made. In simple terms, two offers are matched and each party receives their items/coins. The implication of this is that one offer is always instantly completed and the other offer has always been waiting, even if it’s only been a few seconds. When considering item-flipping, this means that an “Instant Buy” price is the same thing as a “Non-Instant Sell” price, and “Instant Sell” is the same as “Non-Instant Buy”. This is the governing principle of item-flipping.

    Trade Limits

    A trade limit is the amount of items which you can buy on the GE in a 4 hour period. There is no limit on how many you can sell. This was implemented to prevent one person from being able to hoard all of the supply on a given item and manipulate their prices. There is no way to increase the trade limit in the Grand Exchange, your only option is to wait for your 4 hour period to roll over, or to buy from other players. There is no limit on player to player exchanges.

    The trade limit is important to consider because it limits the amount of profit possible for a given item. The trade limit for every item is listed comprehensively on RSWikia. It is very important to note that some item limits are linked together. For example, bronze to adamant platebodies have a linked trade limit of 500, while rune platebodies have a separate limit of 100. For a list of linked limits, see this guide.

    GE Updates

    At the beginning of this section, I said that Market Price is a summary of the previous 24 hours of trading. This is true, but the GE updates approximately once per day and the schedule is not exact. Sometimes it is 30 hours, sometimes it is 18 hours. The market price is still an average of the previous update’s trading, but you cannot anticipate the update and invest right before it. For all practical investing it is safe to assume that the GE updates the Market Price once per day at a given time. I like to pretend that the update occurs at exactly midnight in my time zone, because I’m asleep then. In practice, it usually happens sometime during the day for me, but it isn’t something that I worry too much about. The time you select will never match up perfectly with the actual update schedule, so choose to think whatever is convenient.




    Analysis Basics

    Introduction

    Price graphs are undoubtedly the single most important thing required for successful investing. If you only understand one thing from this entire tutorial, please let it be this topic. The graphs provided by RS are extremely simple. They provide price data on the Y-axis (vertical) and time on the X-axis (horizontal). These graphs show the daily average, and can show the 1-month, 3-month, and 6-month averages as well.


    Graphs can assume two basic shapes: The first is a continuous (smooth) graph and the second is what I refer to as a “step” graph. Continuous graphs are traded frequently enough that the price is updated every day with either an increase or decrease, while only occasionally having the price stay the same from one day to another. Step graphs are traded infrequently, and often go days without having a price update. For our purposes (making money) the only type we care about is continuous graphs, like the one above. This is because the price changes in step graphs are so infrequent that your profit will take a much longer time to achieve.

    Trends

    In price graphs, there are two basic trends which we need to be aware of. They are uptrends (or upwards trends) and downtrends (or downwards trends). The below pictures indicate these two types of trends.

    Uptrend:



    Downtrend:



    When looking at trends, it is important to remember the length of the trend. An item can be going through a short term (few days) downtrend while actually enjoying a long term (weeks or months) uptrend. Always remember that no matter what direction the current trend is, the daily average is still capable of going in the opposite direction for the short term (a day or two) before returning to the trend. If you are analyzing trends, do not get caught up looking at the “trend” from one or two days. A proper medium term trend may take weeks to fully develop, try not to be fooled by one-day jumps in the opposite direction.

    Basic investing theory tells us we should buy when an uptrend starts, and sell when it ends. How do we actually know when this is happening though? That’s where more advanced methods, experience, and common sense will help immensely.

    Support and Resistance

    This is your first “advanced” technique that will help you determine when to invest and when to dump an item. Support and resistance are imaginary lines that provide boundaries for the price of an item. The support level is the price which an item cannot drop past, and the resistance level is the price which an item cannot rise above. When a price begins dropping, it will hit the support level and begin rising again. This is when you should buy the item, because you know it will rise back up. The graph below is a simple graph I made in Excel showing the support and resistance levels for Coal over a 30 day period.


    If you’re looking at the graphs and thinking “Yeah this is great, but how do I know how to draw these lines?” then you’ve discovered the one major downside of support/resistance levels. These lines are nearly completely objective, and two people could come to completely different estimates of their value. Including points from further back in time may help or make it worse for you, and this is why experience is very important. The more you practice, the better you will get at estimating support levels and hence the more money you will make from your investments. However, to get you started I’ll give a brief explanation of the theory behind drawing your own lines.

    Because we want to make money, we only really care about investing in items with an uptrend. This is when support levels are useful. So find a graph with an uptrend and copy it into your favourite image editor. The key to drawing support lines is to pick a few “valleys” in your price graph and draw a line which crosses all of these lines. If there are no other “lows” which are below your line, then you’ve drawn a proper support line. If there are lows below the line you’ve drawn, your line will need to incorporate them in order to be a proper support line. The graph below shows support/resistance levels drawn in paint for Cannonballs.


    You’ll probably notice that sometimes there are “mini-support” levels where the price doesn’t reach the support before going back up. There are many cases where the support and resistance are not as clean as the examples that I have selected. When an item drops below its support level, you should expect the price to begin falling even further and sometimes very rapidly. If a price drops below the support level, you should look into selling the item.

    Choosing Items

    So far we’ve learned to buy at support levels and sell at resistance levels (or to buy on uptrends and sell on downtrends, depending on how you look at it), how do we know what items are best to practice on? The best items for your practice are items that are sold in bulk. This can be runes, ores, logs, etc. Anything that is a resource and consumed for various skills will be a good starting point. This is part of the reason why my MerchantAid uses the top 100 traded items exclusively. The other benefit of using only highly traded items is that there is no worrying about your offers taking a long time to complete. These items can be easily instant-bought and instant-sold without altering your profit margins too much.

    So you have a list of items that you’d like to start merchanting. How do you know what the best items are? At this point, you’re best to try determining the support and resistance points of these items and predicting if one of the items is near its support level. You can then buy that item (or just make a mental note and come back the next day to see if the item rose or not). If the item rose after touching the support level, you’ve made a successful prediction.

    There are more advanced tools which can be used to supplement these predictions and help you decide which items are best to invest in even if they aren’t at their support levels. If you’re interested in learning those, continue reading on to the next sections.

    Investing Tips

    As you’re starting off investing, it’s best to experiment with as many items as possible. Try to spread your wealth around so if you’ve guessed wrong you won’t lose all of your money. The rule of thumb in real life stocks is different depending on who you talk to and how risk-averse they are. My rule of thumb for RS investing is to put no more than 20% of your money into a single item. As you start out, you might find that you don’t like risking 20% of your money on an item, and you would prefer limiting it to 5%. This is perfectly acceptable, everyone has different risk preferences and you should figure out what you’re comfortable with.

    It is extremely important to always be patient with investing. Market prices update once daily, so there isn’t a lot of data you can get in between updates. It also can take weeks for trends to appear, and you have to be patient through the “mini-valleys” that I spoke of earlier. Always remember to take your time and double check all offers before confirming. You can easily lose millions by having a careless mistake in an offer.

    When determining support and resistance levels, keep in mind that round numbers can be support/resistance levels for the simple reason that buyers/sellers prefer round numbers when setting prices. Market psyche will cause prices to hit a limit at important round numbers (which vary depending on the price of the item).

    While you have to make sure not to risk too much on a single item, it’s important to not tie up all of your cash in general as well. You want cash so you can enjoy the game, you should leave yourself whatever cushion you need in order to do that. Don’t miss out on fun because you’re waiting on Coal to reach a resistance level in a couple weeks to sell off and make a few million profit.

    Finally, I’ll finish off the tips with a few business rules I’ve picked up over my years.
    1. Never run out of cash
    2. Cash is king
    3. Cash now is better than (the same amount of) cash later
    4. Never, EVER, EVER, run out of cash





    Advanced Graph Reading

    More Support and Resistance


    The technique I will explain here is referred to as “Swing Trading” in this Smokin’ Mils tutorial. It involves finding a highly stable item and making many short term investments to provide stable income regardless of if the item is in an uptrend or a downtrend.

    Let’s look at the graph I provided above showing coal:


    We can see that in this graph, there is a very repetitive pattern of oscillations. Buying and holding onto coal from 210gp (at the lowest point) to 222gp (the highest point) is about a 5% profit. However, if you bought at every support level and sold at every resistance level you could earn about 4% per oscillation.

    So if you started with 10k, you’d buy 47 coal (and have 130gp left). Then you could sell that 47 coal 3 days later for 10293 (plus 130 = 10423gp). You could wait a couple days, then buy the coal again at 211gp to get 49 coal (and 84gp) and sell for 220gp for 10864gp (including the 84gp). So instead of holding onto coal for 30 days and getting 10564gp, after the four “cycles” here, you could have 11740gp, which is 3 times more profit. The same math applies if you started with 100M, you would have 117M after a month, without having to put more than 15 minutes into investments every few days.

    Advanced Graph Trends

    The techniques in this tutorial come from the same Smokin’ Mils tutorial as the above section. I will summarize the important types of graph trends and their implications on GE graphs and investing.

    The two easy and important trends to keep in mind are converging/diverging trends. These two trends can cause extreme price shifts and make incredible investment opportunities. The below explanation of converging trends is taken from the linked tutorial.


    You can see the below graph for Babydragon Bones has a downward converging trend which is followed by a significant increase in the price once the price breaks past the resistance line. This is the “go-to” trend that you should be looking for, because once the price breaks through the resistance level, you can stand to make significant money.


    The upwards converging trend is shown in the graph of Swordfish below. This is the bad converging trend, and it means that you should expect the price of the item to drop. Do not invest in these trends unless you like the risk or know when to bail.


    The below explanation of diverging trends is taken from the linked tutorial:


    The graph below shows the price of raw lobster over 6 months. The long-term support and resistance levels are shown as well. You can see that this is an upward diverging trend. This is the “bad” kind of diverging trend.


    You can see why this would be considered the bad kind of diverging trend. Once the price crosses the support level, it takes an extreme dive. This is not the kind of trend that you typically want to invest in. The kind that you want to invest in is a downward diverging trend, shown below as the price of Luminous Energy.





    Item Flipping

    Introduction to Item Flipping

    Item flipping is fundamentally extremely basic. It focuses exclusively on the theory I mentioned in “Making the Transaction”. There is a general spread of prices between the instant-sell (low price) and the instant-buy (high price) for an item. You stand to make good profit if you can buy at the instant-sell price and sell at the instant-buy price. The downside to this is that in order for an “instant” sell to work, there has to be a “partner” who has been waiting with an offer. In this case, you are the waiting partner.

    Some items have a fast turnaround time (an hour or so) and some items have a very slow turnaround time (overnight – ie 10 hours or so). These times largely depend on the volume of the item being traded and the amount of people currently trying to flip it. High volume items (ie top 100 traded) should be expected to have high turnaround times, but they typically have lower profit margins. Items which other people are flipping will be harder for you to flip, because there are multiple “partners” waiting for trades to occur. For that reason, I will not mention any specific items in this whole tutorial. Other people on the internet are kind enough to provide item lists, but you should expect that these items will have competition. Finding items that work for your preferences and patience level is key to flipping.

    Finding an Item

    So I said I would not give any specific items for people to try. How are you supposed to figure out where to start then? I’ll go easy on you and say that any list you find with a Google search is probably good enough to start practicing. These lists are simply items that people have found work for them, it’s not like there’s a lot of science behind it. Grab a list, grab an item, and move on to the next step. From there you’ll find it helps to keep track of what profits you made with each item, and you’ll soon have a list of your own “favorite” items. Just go try random items, there’s always going to be some split between auto-buy and auto-sell price, you’ll find out what items give you the most profit without having to wait for a day.

    How to Determine Profit

    So you picked an item, now you need to know how to flip it. Let’s assume you’ve chosen Nature Runes, which are a very popular item. Put in a buy offer for 1 Nature Rune at +20% price. Keep in mind that this means “+20% or less” because you always get the best price that is below your offer. The item should auto-buy and you’ll get coins and a single item. If it doesn’t auto-buy, you should abort the offer and try again at +25% or +30% until the item finally buys. Write down the price that you bought the item for (the actual price). Below you can see that I offered to buy 1 Nature Rune for 344gp (+20%) and it actually bought for 288gp.


    Now, sell the item at -20%, which means “-20% or higher”. It should auto-sell. If not, do the same as if it didn’t auto-buy, keep decreasing the offer price until it does. Once it sells, write down the price that it sold for. Below you can see I offered to sell the Nature Rune for 231gp (-20%) and it actually sold for 286gp.


    So you have two prices, and you’re almost ready to flip your Nature Runes. Keeping in mind that the GE pairs up the best deal with an auto-buy/sell, you want to make sure you have the best deal so you can quickly flip the item. You don’t need to get too feisty; you only need to be 1gp better than the original prices you found. I bought my Nature Rune for 288gp and sold it for 286gp. In order to be the best offer, I need to buy for 287gp (1gp higher than the auto-sell price) and sell for 287gp (1gp lower than the auto-buy price). This is your profit margin (for this example there is no profit margin). This is when you should decide if a flip is worth it or not. It’s completely up to you to decide if it’s worth it or not, but I usually aim for at least a 2% profit margin.

    Performing the Flip

    Assuming you’ve decided to flip this item, you go into the GE and make a buy offer. You cannot try to buy to the trade limit though; you’ve already traded 2 items. So you can only buy 2 less than the trade limit. Make a buy offer for the desired quantity of items at 1gp higher than your instant-sell price.

    Then you wait until your offer is complete and sell your items for 1gp lower than your instant-buy price.

    Congratulations, you’ve completed your flip!

    Flipping Tips

    Some people might look at the instructions above and say “well I’m going to offset my prices by 10gp to make it go faster”. This actually doesn’t help. You’re simply cutting the profit margin for yourself and anyone else who tries to flip the item. In terms of speed, 1gp and 100000gp off from the buy/sell prices will be the same speed, but 1gp will give you much higher profit margins.

    If you find that your item has stopped buying or selling after a while, it’s likely that the item’s margins have changed. You should put in another instant buy offer to check the sell price and then sell the item to check the buy price. If these prices have shifted, you have to cancel your offer and re-buy/sell at the new prices. If you’re in the first 20-30 minutes of buying/selling though, I recommend waiting because it’s possible that the item simply isn’t traded too often. Keep in mind you could be wasting profit by trying to
    Last edited by 3Garrett3; 04-04-2015 at 04:25 AM.

    Scripts: Edgeville Chop & Bank, GE Merchanting Aid
    Tutorials: How to Dominate the Grand Exchange

    Quote Originally Posted by YoHoJo View Post
    I like hentai.

  2. #2
    Join Date
    Feb 2007
    Location
    Alberta, Canada
    Posts
    4,615
    Mentioned
    50 Post(s)
    Quoted
    429 Post(s)

    Default

    Part 2 – Technical Analysis

    So you’ve officially made it to Part 2. We learned some exciting things together in Part 1, and I hope you made some cash in the process. In fact, Part 1 was so successful that Part 2 has to be at least 10x more exciting right? Well my friend, you’ve never been more wrong. This portion is only for people who like a little math in their diet. This is for the people who like a little adding, a little multiplication, and even a couple mentions of standard deviation. If that stuff isn’t for you, I’m going to try to help you through this as well as I can. For every method, I will include pictures to show visually how to determine when to buy and when to sell.


    Intro to Technical Analysis

    Technical analysis can get pretty complicated in the real world. Luckily, I find that the simple techniques I’m going to explain have worked fairly well on the Grand Exchange, and the best part is that the math is not anything harder than what you learned in middle school. Technical analysis is a fancy term for the study of supply and demand to help predict future price movements. The basic assumptions of technical analysis are:

    1. The price of an item reflects everything about the item. This includes all economic factors (supply and demand) as well as market psychology. This means that the price of an item is the only thing we care about when doing technical analysis.
    2. Prices move in trends.
    3. History tends to repeat itself.

    The biggest limitation on this type of analysis is that all items must have significant trade volumes. This is a requirement, or there is a much higher chance that your item does not follow the above 3 assumptions because it is subject to more individual manipulation. This also means that technical analysis is not reliable for predicting the price of rares or other items which are infrequently traded.

    The only time that volume information is available in the GE is for the top 100 traded items. If you’re working with those, you have a slight advantage compared to the rest of the items. The price of an item will normally follow volume. If there is a sudden spike in trading volume, the price of an item will increase while if the traded volume suddenly decreases, you should expect the price to decrease.

    When using technical analysis, the #1 piece of advice I can give you is to always use common sense when trading. Don’t rely on one method only. Each method is subject to different types of false-positives and no prediction method is 100% accurate. Hopefully by considering the recommendations of the methods below with your experience from Part 1, you can find the perfect merchanting items and reap the benefits.

    How to Manage Data

    In the previous section, I covered the fact that the price of an item is the only data point that we care about. That’s pretty easy, right? All we need is the price of an item and we already know everything. In order to get the trend of an item though, we need many price points. Jagex is nice enough to provide the historical data from the GE for us, so we can simply use Simba to gather all the data and present it for us. The snippet below (credit to slacky for the good parts, me for the rest) is how I’ve gathered prices for use in my MerchantAid script.

    Simba Code:
    function RS_GetPricesOf(Item : String; numSamples: Int32 = 100): TIntegerArray;
    var
      i : Integer;
      ID, Page, fullPage, RSpage, str, link: string;
      items: TStringArray;
    begin

      item := Replace(item, ' ', '_', [rfReplaceAll]);
      fullPage := GetPage('http://runescape.wikia.com/wiki/Exchange:' + Item);
      ID := extractFromStr(between('"GEDBID">', '</span>', fullPage), Numbers);

      link := 'http://services.runescape.com/m=itemdb_rs/'+ Item + '/viewitem.ws?obj=' + ID;
      rsPage := getPage(link);
      Items := MultiBetween(RSPage, 'average180.daily.push(',');');

      if numSamples > Length(items) then
        WriteLn(Format('[Hint] NumSamples overflow: Could only gather %d samples', [High(items)]));
      for i := Max(High(items) - numSamples, 0) to High(items) do
        Result.Append(strToInt(items[i]));
    end;

    We have a couple options in terms of working with the price data; either we code the math into Simba and work there, or we export the prices into Excel. Both of these methods have their benefits. Excel can display data which makes it easier to visually determine trends, but Simba can run through many items much faster. The below code will grab the prices of an item and export to a .csv file which can be imported by Excel.

    Simba Code:
    program priceToExcel;
    {$i srl-6/srl.simba}

    const
      theItem = 'Lobster'; // What item you want to grab prices for
      amountOfPrices = 160; //160 is the max

    var
      scriptStartTime : String;

    function RS_GetPricesOf(Item : String; numSamples: Int32 = 100): TIntegerArray;
    var
      i : Integer;
      ID, Page, fullPage, RSpage, str, link: string;
      items: TStringArray;
    begin

      item := Replace(item, ' ', '_', [rfReplaceAll]);
      fullPage := GetPage('http://runescape.wikia.com/wiki/Exchange:' + Item);
      ID := extractFromStr(between('"GEDBID">', '</span>', fullPage), Numbers);

      link := 'http://services.runescape.com/m=itemdb_rs/'+ Item + '/viewitem.ws?obj=' + ID;
      rsPage := getPage(link);
      Items := MultiBetween(RSPage, 'average180.daily.push(',');');

      if numSamples > Length(items) then
        WriteLn(Format('[Hint] NumSamples overflow: Could only gather %d samples', [High(items)]));
      for i := Max(High(items) - numSamples, 0) to High(items) do
        Result.Append(strToInt(items[i]));
    end;

    procedure startTime;
    var
      Hour, Mins, Sec, MSec: Word;
      Year, Month, Day : UInt16;
      suffix : String;
    begin
      DecodeTime(Now, Hour, Mins, Sec, MSec);
      DecodeDate(Now, Year, Month, Day);
      if Hour < 12 then Suffix := 'AM' else Suffix := 'PM'
      if Hour > 12 then Hour -= 12;
      scriptStartTime := (' ' + toStr(Day) + '-' + toStr(Month) + '-' + toStr(Year) + ' at ' + Padz(IntToStr(Hour), 2) + Padz(IntToStr(Mins), 2) + Suffix);
    end;

    procedure WritetoFile(theArray : TIntegerArray; Item : String);
    var
      path, str, txt: String;
      theFile, i, j : Integer;
    begin
      try
        path := ScriptPath + Item + ' ';
        theFile := RewriteFile(path + scriptStartTime + '.csv', False);

        txt := 'Day:,';
        for i := 0 to high(theArray)-1 do
          txt := txt + toStr(i) + ',';
        txt := txt + toStr(high(theArray));

        txt := txt + [URL=https://villavu.com/forum/usertag.php?do=list&action=hash&hash=1]#1[/URL] 3[URL=https://villavu.com/forum/usertag.php?do=list&action=hash&hash=1]#1[/URL] 0 + Item + ',';
        for i := 0 to high(theArray)-1 do
          txt := txt + toStr(theArray[i]) + ',';
        txt := txt + toStr(theArray[high(theArray)]);

        WriteFileString(theFile, Txt);
        CloseFile(theFile);
      except
        Writeln('Debug saving - error occurred');
      end;
    end;

    begin
      startTime();
      WriteToFile(RS_GetPricesOf(theItem, amountofPrices), theItem);
    end.

    To use this code, simply indicate the item you want to work with and the amount of values you want and press run. You might assume that because Jagex says they keep 180 days of price data, you would be able to grab 180 price points for analysis. They’re actually lying to you and only providing about 165 data points though, so keep your requests to 160 and below and you should be fine.

    Methods

    The following is a list of the methods I will be describing in the following sections.

    1. Moving Averages – Comparing a short-term average against current prices.
    2. Relative Strength Index (RSI) – This indicates over-sold and over-bought items.
    3. Aroon Indicators – This indicates the direction and strength of a trend.
    4. Stochastic Oscillators – Shows trend momentum. Can be used as a ‘trigger’ indicating buy and sell points.
    5. Bollinger Bands – Measures the volatility of an item. Can also be used to indicate buy/sell points.

    How to Use the Following Sections

    The sections describing each indicator will be broken down into 2 mini-sections. The first will describe the usage and theory of why it works with a graph showing how I would recommend determining if you should buy or sell. The second will describe the math required to produce them and show you the code I’ve used for it. If you’re not interested in the math, hopefully you can still get something out of the theory and graphs and then just copy and paste the Simba code if you’d like to use it. To save me from having to retype math, I’ll simply be linking to what I consider a really good description of how to use the methods in the real world. At the end of the sections describing all methods, I will provide the entire script which accepts an item and number of days and outputs the Excel file with the results of all calculations. The Excel files from this script are used for all examples in the sections below.

    The idea I’ve used is to combine the “buy” or “sell” recommendations for each item. I then make my decision based on the total recommendation. No single indicator is “better” than the others, and all are useful in one way or another. To make the best decision and avoid false-positives, combining all methods into a single buy/sell indicator is recommended. To help you along following these ideas, I’ll be using a graph for Lobster over the last 160 days. The price graph for Lobster over this time period looks like this:



    Moving Average Usage

    The simple moving average is a good tool to determine the momentum of an item, that is; what direction it’s going in and how “strong” the trend is. By taking a short-term average, say the three day average of an item, we can quickly determine the direction of the item by comparing the current price to the moving average. If the current price is above the moving average, then the item is trending up and if the current price is below the moving average then the item is trending down. This is the simplest of the technical indicators, and isn’t something that you would use in a real life stock market, but it provides a quick snapshot of the item’s recent trend.

    Because of the simplicity of this method, you simply buy when the price is above the moving average and sell when the price is below the moving average. Below I’ve graphed the 3 day moving average against the price of Lobster. In the graph, you'll see the blue price line and the orange Moving Average line (values on the left Y axis) and the grey Moving Average Signal line (values on the right axis). Remember that the buy signal is a value of 1 and the sell signal is a value of -1. I've drawn black lines on the diagram showing when every signal indicates to buy or sell, and I've labelled a few of the signals to be clear which means which.



    You can see from this graph that the Moving Average method is very responsive when 3 days are used. There are a few false positives, like selling in the middle of the large uptrend.

    Moving Average Math

    This link shows a very good and detailed explanation of how to calculate and use moving averages for technical analysis.

    Below I’ve implemented the math into a loop to calculate the moving average over a period of X days (where “MADays” = X in this code) for every day in the dataset. It will recalculate the average over the last X days for each day (hence moving average, because it moves for each day).

    Simba Code:
    procedure doMA();
    var
      i, h: Integer;
      avg, comp: Extended;
      tempA: TIntegerArray;
    begin
      for i := 0 to MADays - 2 do
        MARec[i] := 0; // You need at least 2 days to get data

      h := high(Prices); // Defined when we grab prices - we want the same amount of calculations as there are prices
      for i := MADays - 1 to h do //For the rest of the prices, figure out the MA
      begin
        tempA := Prices.slice(i - (MADays - 1), i); // This creates a temporary array from a slice of the price array

        avg := TempA.Mean();      // Grab the average of the values in the temporary slice
        comp := avg - Prices[i];  // The comparison here is between the average and the current day's price

        if comp > 0 then          // If the average is higher than today's prices (we're in a down trend), so rec is -1 (Sell)
          MARec[i] := -1
        else if comp = 0 then     // If the average is the same as today's prices there is no new recommendation (Hold)
          MARec[i] := 0
        else
          MARec[i] := 1;          // If the average is below today's prices (we're in an uptrend), the rec is 1 (Buy)
      end;
    end;

    RSI Usage

    RSI is a measure of the “momentum” of an item. It is a scale from 0-100 which indicates if an item is “overbought” or “oversold”. These terms are pretty self explanatory; if an item is overbought then it is expected to have lower demand soon (and crashing prices), while an oversold item is expected to soon have higher demand (and higher prices). On the scale, “oversold” is anything below 30 and “overbought” is anything above 70. Anywhere in between and the item is trading roughly as expected. If you feel more conservative, you can also use cut-offs of 20 and 80 for oversold and overbought, respectively.

    The RSI method works on crossovers of the overbought and oversold lines. If the RSI score crosses from below the oversold line to above it, we treat it as a buy signal. If the score drops from above the overbought line to below it, we treat it as a sell signal. Below I’ve graphed the 4 day RSI value and shown where the buy and sell signals are. Like the Moving Average graph, the prices are in blue (left Y Axis) and the RSI Value is in orange (right Y Axis). The overbought and oversold boundaries are in grey/yellow, respectively. I've marked all buy and sell signals in black and labelled a few of them.



    From this graph you can see that there are less signals with the RSI method than the Moving Average method, as well as less false-positives, but it misses some of the smaller gains and is a little slower to respond on the large ones due to the 4 day parameter instead of the 3 days of moving average.

    RSI Math

    This link gives a good explanation of how to calculate RSI and a good description of the buy and sell signals that can be generated.

    In the below code I’ve got the method to calculate the X-day RSI score (where RSIDays = X) for an entire set of prices.

    Simba Code:
    procedure doRSI();
    var
      i, h, change : Integer;
      Gains, Losses, tempG, tempL : TIntegerArray;
      avgG, avgL, RSI: Extended;
    begin
      h := high(Prices); // Defined when we grab prices - we want the same amount of calculations as there are prices

      SetLength(Gains, h+1);
      SetLength(Losses, h+1);

      Gains[0] := 0;    // The first day you can't take a comparison of gain or loss, set both to 0
      Losses[0] := 0;

      for i := 1 to h do // You can do comparision from day 1 (second day) to the last day, do comparisons
      begin
        Change := (Prices[i] - Prices[i-1]);  // The change from Day[i-1] to Day[i]

        if Change > 0 then Gains[i] := Change else Gains[i] := 0; //If change is positive, add it to gains (else gains is 0)
        if Change < 0 then Losses[i] := (0-Change) else Losses[i] := 0; //If change is negative, add it to losses (else losses is 0)
      end;

      for i := 0 to RSIDays - 2 do   // This is where we start assigning scores
        RSIRec[i] := 0;      // Can't have scores for the first (RSIDays - 2) Days (not enough data points)

      for i := RSIDays - 1 to h do
      begin
        tempG := Gains.Slice(i - (RSIDays - 1) , i);  // The temporary gains and losses arrays are generated for processing
        tempL := Losses.Slice(i - (RSIDays - 1), i);

        avgG := tempG.Mean(); //Take the average of each slice
        avgL := tempL.Mean();

        if avgL = 0 then  // This saves us from dividing by 0, the RSI Score is set to 100
          RSIValue[i] := 100
        else
          RSIValue[i] := 100 - (100 / (1 + (avgG/avGL))); // This is the main calculation after the above processing

        if (RSIValue[i-1] > RSIUpper) and (RSIValue[i] < RSIUpper) then RSIRec[i] := -1  // If we cross from above overbought to below, that's a sell signal
        else if (RSIValue[i-1] < RSILower) and (RSIValue[i] > RSILower) then RSIRec[i] := 1  // If we cross from below oversold to above, buy signal
        else RSIRec[i] := 0;                             // If neither of those options, no rec (Hold)
      end;
    end;

    Aroon Indicator Usage

    There are actually two parts to the Aroon Indicator; the “Aroon Up” and “Aroon Down” indicators combine together to create a single number. The Aroon Up indicator shows the “strength” of an uptrend in the data, while the Aroon Down indicator shows the “strength” of a downtrend in the data. Aroon Up is represented by 0-100, Aroon Down is -100-0, and when the two are added together you get a single value between -100 and 100.

    The simplest interpretation for the Aroon Indicator is that when the value is greater than 0, the item is in an uptrend and when it is below 0, the item is in a downtrend. You should buy when in an uptrend, and sell when in a downtrend. Values close to 0 indicate “sideways movement” meaning there is no significant trend in either direction. Below I’ve graphed the 7 day Aroon score over 160 days of Lobster prices. Again, the prices are in blue (left Y Axis), the Aroon Indicator is in orange, and the zero line is in grey (both right Y Axis).



    You can see that by using the 7 day parameter, there is a significant lag in the Aroon indicator compared to the 3 and 4 day Moving Average and RSI algorithms. The indicator is slower to pick up changes but has less false positive readings.

    Aroon Indicator Math

    This link has a very good explanation of how to calculate the Aroon Indicator and how to use it as a buy/sell signal. Below is the code I’ve used to follow this method of calculation. It will calculate the Aroon Indicator value for a set of prices

    Simba Code:
    procedure doAroon();
    var
      i, h, maxDay, minDay: Integer;
      upDir, downDir, Aroon: Extended;
      tempA: TIntegerArray;
    begin
      h := high(Prices); // Defined when we grab prices - we want the same amount of calculations as there are prices

      for i := 0 to AroonDays - 2 do
       AroonRec[i] := 0;

      for i := AroonDays - 1 to h do
      begin
        tempA := Prices.Slice(i - (AroonDays - 1), i, False);  //Reverse so that newest days are 0 and increasing, so high today gives 0 as index (0 days since high)
        maxDay := tempA.argMax();                                   //Gets the index of the maximum price (days since high price) in the slice
        minDay := tempA.argMin();                                   //Gets the index for the low price (days since low price) in the slice

        upDir := 100 * (((AroonDays - 1) - MaxDay) / (AroonDays - 1)); // The Aroon Up score
        downDir := 100 * (((AroonDays - 1) - MinDay) / (AroonDays - 1)); // The Aroon Down score
        AroonValue[i] := upDir - downDir; // Gives the overall Aroon score

        if upDir > downDir then // If we are net-positive score (uptrend) then buy
          AroonRec[i] := 1
        else if upDir < downDir then // If we are net-negative score (downtrend) then sell
          AroonRec[i] := -1
        else
          AroonRec[i] := 0;    // If the score is 0 then no rec (hold)

      end;
    end;

    Stochastic Oscillator Usage


    The Stochastic Oscillator is two lines on a graph, the %K line and the %D line. The K line is the ‘fast’ line and the D line is the ‘slow’ line. Because the K line responds to price faster than the D line, we can create two main signals from this method. A buy signal is created when the K line goes from below to above the D line, suggesting that the price is starting to move up. A sell signal is created when the K line goes from above the D line to below it, suggesting the price is starting to go down. Some people also add the element of overbought and oversold in this context, and only buy when both the D and K line are below 30 and the K line goes above D. They then only sell when the D and K line are above 70 and the K line goes below D. I do not use this method though.

    Suggested interpretation: When K goes from below D to above D, buy. When K goes from above D to below D, sell. The Stochastic Oscillator and the RSI go very well together, and a buy signal from both is to be taken more seriously than other combinations, because they indicate the same things (overbought/oversold) in different ways. Below I’ve graphed the 6 day (3 day %K and 3 day %D) Aroon Indicator for Lobster over 160 days. Prices are in blue (left Y Axis), the %K (grey) and %D (orange) lines are shown and their values are on the right Y Axis. You can see that using 3 day parameters causes many buy/sell signals for the Stochastic Oscillator. It is very responsive but falls victim to many false positive readings. I've indicated where every signal is in black and labelled the few signals which had room.



    Stochastic Oscillator Math

    This link contains an explanation of the methods of using stochastic oscillators and how to calculate them. Below is the code I use to calculate the “fast” stochastic oscillator (which is graphed above).

    Simba Code:
    procedure doStoch();
    var
      i, h : Integer;
      minP, maxP: Integer;
      d: Extended;
      k: TExtendedArray;
      tempA : TIntegerArray;
    begin
      h := high(Prices); // Defined when we grab prices - we want the same amount of calculations as there are prices

      for i := 0 to (StoKDays + StoDDays) - 3 do // It works out that we can't have recs for this range
        StoRec[i] := 0;

      for i := 0 to StoKDays - 2 do   // There can be no K values for this range
        StoKValue[i] := 0;

      for i := (StoKDays - 1) to h do // Generate the k values
      begin
        tempA := Prices.Slice(i - (StoKDays - 1), i);  // Generate our temporary range
        minP := MinA(tempA);   // Gets the lowest value (price)
        maxP := MaxA(tempA);   // Gets the highest value (price)

        if (maxP - minP) <= 0 then  // Saves us from divide by 0 errors
          StoKValue[i] := 100  // Maximum k is 100
        else
          StoKValue[i] := 100 * ((tempA[high(tempA)] - minP) / (maxP - minP)); // The actual formula for the k values
      end;


      for i := (StoKDays + StoDDays - 2) to h do
      begin
        StoDValue[i] := StoKValue.Slice(i - (stoDDays - 1), i).Mean();  // Takes the moving average of k values

        if StoDValue[i] > StoKValue[i] then        // If current k value is under moving average (going below the average), sell
          StoRec[i] := -1
        else if StoDValue[i] < StoKValue[i] then   // If current k value is over moving average (going above the average), buy
          StoRec[i] := 1
        else
          StoRec[i] := 0;
      end;
    end;

    Bollinger Band Usage

    Bollinger Bands ® (yes they are registered) are a series of three lines; a center (average) line and two “channels/bands”. One band is above the center and one is below. The center line is typically an exponential moving average (although I just use the price) and the price channels show the standard deviation of the stock. The channels will be narrow for very stable stocks and will be very wide for volatile stocks.

    There are many uses for Bollinger Bands in the real world stocks, but in RS I’ve used the simplest way to get buy/sell signals. The channels are used as overbought and oversold indicators, which can then be treated the same as most of the above signals I’ve explained. When the price of a stock touches (or goes over) a channel, you prepare for the signal. When it moves away from the channel, coming back towards the average, you have a signal. If it touches the lower band and comes back towards the average, the signal is to buy. If the price touches the upper band and comes back to average, the signal is to sell. Below is a graph showing the 6 day Bollinger Band for Lobster over 160 days.

    As usual, the price is in blue (left Y Axis), the upper and lower channels of the Bollinger Bands are orange and green, respectively (also left Y Axis), and the buy/sell signals are shown in grey (right Y Axis). I've indicated the buy and sell signals in black and labelled one pair for clarity.



    You can see from this graph that the bands were good at indicating buy/sell signals in the first 30 days, but were generally bad after that. This is why I don't recommend using only one indicator, because sometimes they'll be good and sometimes they'll be bad.

    Bollinger Band Math

    This link is an excellent description of how to calculate Bollinger Bands in Excel. In a great twist of events, this tutorial specifically warns not to use the Bollinger Bands in the way that I’ve chosen to. I have found that while the method I’ve used is not the most active signal (not very many signals), it serves very well to help verify the rest of the methods.

    Below is the code I’ve used to determine the Bollinger Band signals for a given price array.

    Simba Code:
    procedure doBollinger();
    var
      i, h : Integer;
      tempA: TIntegerArray;
      avg, SD, SDMult: Extended;
      touchUpper, touchLower: TBoolArray;
    begin
      h := high(Prices); // Defined when we grab prices - we want the same amount of calculations as there are prices
      SetLength(touchUpper, h + 1);
      SetLength(touchLower, h + 1);

      for i := 0 to BollDays - 2 do
      begin
        BollRec[i] := 0;
        BollUpper[i] := 0;
        BollLower[i] := 0;
        touchUpper[i] := False;
        touchLower[i] := False;
      end;

      for i := BollDays - 1 to h do
      begin
        tempA := Prices.Slice(i - (BollDays - 1), i); // Grabs our temporary array
        avg := tempA.Mean();       // Takes the average
        SD := tempA.StdDev();      // Takes the standard deviation

        BollUpper[i] := (Avg + (SD * 1.9)); // This calculates the upper band
        BollLower[i] := (Avg - (SD * 1.9)); // This calculates the lower band

        touchUpper[i] := (Prices[i] >= (BollUpper[i] * (1 - (1 / 100)))); // Are we touching the upper band? Within 1%
        touchLower[i] := (Prices[i] <= (BollLower[i] * (1 + (1 / 100)))); // Are we touching the lower band? Within 1%
      end;

      for i := BollDays - 1 to h do
      begin
        if touchLower[i-1] and (not touchLower[i]) then     // If we were touching lower and aren't anymore, buy signal
          BollRec[i] := 1
        else if touchUpper[i-1] and (not touchUpper[i]) then // If we were touching upper and aren't anymore, sell signal
          BollRec[i] := -1
        else
          BollRec[i] := (0);
      end;
    end;

    What We Learned

    From these methods, you’ve hopefully learned a few important things. First, you can see that the amount of days you use to determine each signal has a huge impact on your results. Having a higher number of days will create less buy/sell signals and can be slower to react to price changes, causing you to potentially miss out on profit, like seen on the Bollinger Band graph. Using too low an amount of days can create false-positives and too many buy/sell signals, which can also cause you to miss profit, like on the Stochastic Oscillator graph. The rule of thumb here is to set the “days” as the amount of days you want to hold an item for, except for with Bollinger Bands when you should use double that amount. I recommend not going less than 3 days for anything, because you will have too many signals to be useful at all.

    The other thing you should notice is that while all signals are roughly in the same area, some signals perform better in some areas and some signals perform better in others. This is why I combine signals to determine the best buy and sell times. Let’s see what happens when we combine all signals from the above sections into a single graph. In the graph below, the sum of all signals is shown. Remember that all buy signals were given a value of 1 and all sell signals were given a value of -1, so any value above 0 is a buy and any value below 0 is a sell.



    You can see from this graph that there are still many false-positive signals that could be smoothed out. This is likely because I’ve used different values for different algorithms, so some methods are aimed at 3 day trading and others are for 7 day trading. I have not yet figured out a way to determine the best day settings, mainly because there are trillions of combinations you could have, and looping that many values is extremely slow in Simba. Even though the combination is not optimized, we still can tell there is a much higher profitable trade ratio than any of the individual methods.
    With all of the learning out of the way, here is the code I’ve used. It will save .csv into the same folder as the script. The .csv can be opened in Excel and will contain all of the information I’ve used to create the graphs in this section. Thanks for reading, and best of luck! If you have any questions, comments, etc. please post and let me know.

    Simba Code:
    program priceToExcel;
    {$i srl-6/srl.simba}

    const
      theItem = 'Lobster'; // What item you want to grab prices for
      amountOfPrices = 160; //160 is the max

      MADays = 3;
      RSIDays = 4;
      StoKDays = 3;
      StoDDays = 3;
      AroonDays = 7;
      BollDays = 6;

      RSIUpper = 70;
      RSILower = 30;

    var
      scriptStartTime : String;
      Prices : TIntegerArray;
      MAValue, RSIValue, StoKValue, StoDValue, AroonValue, BollUpper, BollLower : TExtendedArray;
      MARec, RSIRec, StoRec, AroonRec, BollRec, TotalRec : TIntegerArray;

    {----------------------------------------------------------------)
    (function tIntegerArray.Slice                                    )
    (Returns a slice of the TIA between given indices (inclusive)    )
    (----------------------------------------------------------------}

    function TIntegerArray.Slice(indexFrom, indexTo : Integer; Forwards : Boolean = True) : TIntegerArray;
    var
      i, x : Integer;
    begin

      if (high(self)) < indexTo then
      begin
        Writeln('TIntegerArray.Slice: Array high is ' + toStr(high(self)) + ', index ' + toStr(indexTo) + ' cannot be reached.');
        Exit();
      end;

      Result := Copy(Self, indexFrom, (indexTo-indexFrom)+1);

      if not Forwards then
        result.invert();

    end;

    {----------------------------------------------------------------)
    (function tExtendedArray.Slice                                   )
    (Returns a slice of the TIA between given indices (inclusive)    )
    (----------------------------------------------------------------}


    function TExtendedArray.Slice(indexFrom, indexTo: Integer; Forwards : Boolean = True) : TExtendedArray;
    var
      i, x : Integer;
    begin

      if (length(self) - 1) < indexTo then
      begin
        Writeln('TIntegerArray.Slice: Array high is ' + toStr(high(self)) + ', index ' + toStr(indexTo) + ' cannot be reached.');
        Exit();
      end;

      Result := Copy(Self, indexFrom, (indexTo-indexFrom)+1);

      if not Forwards then
        result.invert()

    end;

    {----------------------------------------------------------------)
    (function tIntegerArray.Mean                                     )
    (Returns the mean of the given TIA                               )
    (----------------------------------------------------------------}


    function TIntegerArray.Mean() : Extended;
    var
      i, h, sum : Integer;
    begin
      h := high(Self);
      for i := 0 to h do
        sum += Self[i];

      Result := sum/length(Self);
    end;

    {----------------------------------------------------------------)
    (function tExtendedArray.Mean                                    )
    (Returns the mean of the given TEA                               )
    (----------------------------------------------------------------}


    function TExtendedArray.Mean() : Extended;
    var
      i, h : Integer;
      sum : Extended;
    begin
      h := high(Self);
      for i := 0 to h do
        sum += Self[i];

      Result := sum/length(Self);
    end;

    {----------------------------------------------------------------)
    (function tIntegerArray.argMax                                   )
    (Returns the index which contains the highest value              )
    (----------------------------------------------------------------}


    function TIntegerArray.argMax() : Integer;
    var
      i, h, tempInt : Integer;
    begin
      h := high(Self);
      tempInt := self[0];
      Result := 0;
      for i := 0 to h do
        if self[i] > tempInt then
        begin
          Result := i;
          tempInt := Self[i];
        end;
    end;

    {----------------------------------------------------------------)
    (function tIntegerArray.argMin                                   )
    (Returns the index which contains the lowest value               )
    (----------------------------------------------------------------}


    function TIntegerArray.argMin() : Integer;
    var
      i, h, tempInt : Integer;
    begin
      h := high(Self);
      tempInt := self[0];
      Result := 0;
      for i := 0 to h do
        if self[i] < tempInt then
        begin
          Result := i;
          tempInt := Self[i];
        end;
    end;

    {-------------------END TYPE FUNCTION SECTION--------------------)
    (ALL CODE WRITTEN BELOW IS BY GARRETT UNLESS OTHERWISE INDICATED )
    (----------------------------------------------------------------}


    {----------------------------------------------------------------)
    (TIntegerArray.StdDev() - Returns the Std Deviation of an array  )
    (Credit: SuperUser, Modified by Slacky                           )
    (----------------------------------------------------------------}


    function TIntegerArray.StdDev(): extended;
    var
      avg, total: extended;
      i: integer;
    begin
      for i := 0 to High(self) do
        total := total + self[i];

      avg := total / Length(self);
      total := 0;

      for i := 0 to High(self) do
        total := total + Sqr(self[i] - avg);

      result := Sqrt(total / Length(self));
    end;

    procedure TBoolArray.Append(value:Boolean);
    begin
      Self := Self + value;
    end;

    procedure RS_GetPricesOf(Item : String; numSamples: Int32 = 100);
    var
      i : Integer;
      ID, Page, fullPage, RSpage, str, link: string;
      items: TStringArray;
    begin

      item := Replace(item, ' ', '_', [rfReplaceAll]);
      fullPage := GetPage('http://runescape.wikia.com/wiki/Exchange:' + Item);
      ID := extractFromStr(between('"GEDBID">', '</span>', fullPage), Numbers);

      link := 'http://services.runescape.com/m=itemdb_rs/'+ Item + '/viewitem.ws?obj=' + ID;
      rsPage := getPage(link);
      Items := MultiBetween(RSPage, 'average180.daily.push(',');');

      if numSamples > Length(items) then
        WriteLn(Format('[Hint] NumSamples overflow: Could only gather %d samples', [High(items)]));
      for i := Max(High(items) - numSamples, 0) to High(items) do
        //Prices[i] := (strToInt(items[i]));
        Prices.append(strToInt(items[i]));
    end;

    {-----------------------------------------------------------------)
    (function doMA                                                    )
    (Determines the Moving Average Score                              )
    (-----------------------------------------------------------------}


    procedure doMA();
    var
      i, h: Integer;
      avg, comp: Extended;
      tempA: TIntegerArray;
    begin
      for i := 0 to MADays - 2 do
        MARec[i] := 0; // You need at least 2 days to get data

      h := high(Prices); // Defined when we grab prices - we want the same amount of calculations as there are prices
      for i := MADays - 1 to h do //For the rest of the prices, figure out the MA
      begin
        tempA := Prices.slice(i - (MADays - 1), i); // This creates a temporary array from a slice of the price array

        avg := TempA.Mean();      // Grab the average of the values in the temporary slice
        comp := avg - Prices[i];  // The comparison here is between the average and the current day's price
        MAValue[i] := avg;

        if comp > 0 then          // If the average is higher than today's prices (we're in a down trend), so rec is -1 (Sell)
          MARec[i] := -1
        else if comp = 0 then     // If the average is the same as today's prices there is no new recommendation (Hold)
          MARec[i] := 0
        else
          MARec[i] := 1;          // If the average is below today's prices (we're in an uptrend), the rec is 1 (Buy)
      end;
    end;

    {-----------------------------------------------------------------)
    (function doRSI                                                   )
    (Determines the Relative Strength Index (RSI) Score               )
    (-----------------------------------------------------------------}


    procedure doRSI();
    var
      i, h, change : Integer;
      Gains, Losses, tempG, tempL : TIntegerArray;
      avgG, avgL, RSI: Extended;
    begin
      h := high(Prices); // Defined when we grab prices - we want the same amount of calculations as there are prices

      SetLength(Gains, h+1);
      SetLength(Losses, h+1);

      Gains[0] := 0;    // The first day you can't take a comparison of gain or loss, set both to 0
      Losses[0] := 0;

      for i := 1 to h do // You can do comparision from day 1 (second day) to the last day, do comparisons
      begin
        Change := (Prices[i] - Prices[i-1]);  // The change from Day[i-1] to Day[i]

        if Change > 0 then Gains[i] := Change else Gains[i] := 0; //If change is positive, add it to gains (else gains is 0)
        if Change < 0 then Losses[i] := (0-Change) else Losses[i] := 0; //If change is negative, add it to losses (else losses is 0)
      end;

      for i := 0 to RSIDays - 2 do   // This is where we start assigning scores
        RSIRec[i] := 0;      // Can't have scores for the first (RSIDays - 2) Days (not enough data points)

      for i := RSIDays - 1 to h do
      begin
        tempG := Gains.Slice(i - (RSIDays - 1) , i);  // The temporary gains and losses arrays are generated for processing
        tempL := Losses.Slice(i - (RSIDays - 1), i);

        avgG := tempG.Mean(); //Take the average of each slice
        avgL := tempL.Mean();

        if avgL = 0 then  // This saves us from dividing by 0, the RSI Score is set to 100
          RSIValue[i] := 100
        else
          RSIValue[i] := 100 - (100 / (1 + (avgG/avGL))); // This is the main calculation after the above processing

        if (RSIValue[i-1] > RSIUpper) and (RSIValue[i] < RSIUpper) then RSIRec[i] := -1  // If we cross from above overbought to below, that's a sell signal
        else if (RSIValue[i-1] < RSILower) and (RSIValue[i] > RSILower) then RSIRec[i] := 1  // If we cross from below oversold to above, buy signal
        else RSIRec[i] := 0;                             // If neither of those options, no rec (Hold)
      end;
    end;

    {-----------------------------------------------------------------)
    (function doStoch                                                 )
    (Uses Stochastic Oscillator to determine if Over or Under Bought  )
    (-----------------------------------------------------------------}


    procedure doStoch();
    var
      i, h : Integer;
      minP, maxP: Integer;
      d: Extended;
      k: TExtendedArray;
      tempA : TIntegerArray;
    begin
      h := high(Prices); // Defined when we grab prices - we want the same amount of calculations as there are prices

      for i := 0 to (StoKDays + StoDDays) - 3 do // It works out that we can't have recs for this range
        StoRec[i] := 0;

      for i := 0 to StoKDays - 2 do   // There can be no K values for this range
        StoKValue[i] := 0;

      for i := (StoKDays - 1) to h do // Generate the k values
      begin
        tempA := Prices.Slice(i - (StoKDays - 1), i);  // Generate our temporary range
        minP := MinA(tempA);   // Gets the lowest value (price)
        maxP := MaxA(tempA);   // Gets the highest value (price)

        if (maxP - minP) <= 0 then  // Saves us from divide by 0 errors
          StoKValue[i] := 100  // Maximum k is 100
        else
          StoKValue[i] := 100 * ((tempA[high(tempA)] - minP) / (maxP - minP)); // The actual formula for the k values
      end;


      for i := (StoKDays + StoDDays - 2) to h do
      begin
        StoDValue[i] := StoKValue.Slice(i - (stoDDays - 1), i).Mean();  // Takes the moving average of k values

        if StoDValue[i] > StoKValue[i] then        // If current k value is under moving average (going below the average), sell
          StoRec[i] := -1
        else if StoDValue[i] < StoKValue[i] then   // If current k value is over moving average (going above the average), buy
          StoRec[i] := 1
        else
          StoRec[i] := 0;
      end;
    end;

    {-----------------------------------------------------------------)
    (function doAroon                                                 )
    (Determines the Aroon Indicator Score                             )
    (-----------------------------------------------------------------}


    procedure doAroon();
    var
      i, h, maxDay, minDay: Integer;
      upDir, downDir, Aroon: Extended;
      tempA: TIntegerArray;
    begin
      h := high(Prices); // Defined when we grab prices - we want the same amount of calculations as there are prices

      for i := 0 to AroonDays - 2 do
       AroonRec[i] := 0;

      for i := AroonDays - 1 to h do
      begin
        tempA := Prices.Slice(i - (AroonDays - 1), i, False);  //Reverse so that newest days are 0 and increasing, so high today gives 0 as index (0 days since high)
        maxDay := tempA.argMax();                                   //Gets the index of the maximum price (days since high price) in the slice
        minDay := tempA.argMin();                                   //Gets the index for the low price (days since low price) in the slice

        upDir := 100 * (((AroonDays - 1) - MaxDay) / (AroonDays - 1)); // The Aroon Up score
        downDir := 100 * (((AroonDays - 1) - MinDay) / (AroonDays - 1)); // The Aroon Down score
        AroonValue[i] := upDir - downDir; // Gives the overall Aroon score

        if upDir > downDir then // If we are net-positive score (uptrend) then buy
          AroonRec[i] := 1
        else if upDir < downDir then // If we are net-negative score (downtrend) then sell
          AroonRec[i] := -1
        else
          AroonRec[i] := 0;    // If the score is 0 then no rec (hold)

      end;
    end;

    {-----------------------------------------------------------------)
    (function doBollinger                                             )
    (Defines the Bollinger Bands and predicts trends                  )
    (-----------------------------------------------------------------}


    procedure doBollinger();
    var
      i, h : Integer;
      tempA: TIntegerArray;
      avg, SD, SDMult: Extended;
      touchUpper, touchLower: TBoolArray;
    begin
      h := high(Prices); // Defined when we grab prices - we want the same amount of calculations as there are prices
      SetLength(touchUpper, h + 1);
      SetLength(touchLower, h + 1);

      for i := 0 to BollDays - 2 do
      begin
        BollRec[i] := 0;
        BollUpper[i] := 0;
        BollLower[i] := 0;
        touchUpper[i] := False;
        touchLower[i] := False;
      end;

      for i := BollDays - 1 to h do
      begin
        tempA := Prices.Slice(i - (BollDays - 1), i); // Grabs our temporary array
        avg := tempA.Mean();       // Takes the average
        SD := tempA.StdDev();      // Takes the standard deviation

        BollUpper[i] := (Avg + (SD * 1.9)); // This calculates the upper band
        BollLower[i] := (Avg - (SD * 1.9)); // This calculates the lower band

        touchUpper[i] := (Prices[i] >= (BollUpper[i] * (1 - (1 / 100)))); // Are we touching the upper band? Within 1%
        touchLower[i] := (Prices[i] <= (BollLower[i] * (1 + (1 / 100)))); // Are we touching the lower band? Within 1%
      end;

      for i := BollDays - 1 to h do
      begin
        if touchLower[i-1] and (not touchLower[i]) then     // If we were touching lower and aren't anymore, buy signal
          BollRec[i] := 1
        else if touchUpper[i-1] and (not touchUpper[i]) then // If we were touching upper and aren't anymore, sell signal
          BollRec[i] := -1
        else
          BollRec[i] := (0);
      end;
    end;

    {-----------------------------------------------------------------)
    (function totalScore                                              )
    (Totals the score from the above 5 algorithms                     )
    (-----------------------------------------------------------------}


    procedure TotalScore();
    var
      i, h : Integer;
    begin
      h := high(Prices); // Defined when we grab prices - we want the same amount of calculations as there are prices
      for i := 0 to h do
        TotalRec[i] := (MARec[i] + RSIRec[i] + StoRec[i] + AroonRec[i] + BollRec[i]);
    end;

    procedure Setup();
    begin
      SetLength(MAValue, AmountofPrices + 1);
      SetLength(RSIValue, AmountofPrices + 1);
      SetLength(StoKValue, AmountofPrices + 1);
      SetLength(StoDValue, AmountofPrices + 1);
      SetLength(AroonValue, AmountofPrices + 1);
      SetLength(BollUpper, AmountofPrices + 1);
      SetLength(BollLower, AmountofPrices + 1);
      SetLength(MARec, AmountofPrices + 1);
      SetLength(RSIRec, AmountofPrices + 1);
      SetLength(StoRec, AmountofPrices + 1);
      SetLength(AroonRec, AmountofPrices + 1);
      SetLength(BollRec, AmountofPrices + 1);
      SetLength(TotalRec, AmountofPrices + 1);
    end;

    procedure startTime;
    var
      Hour, Mins, Sec, MSec: Word;
      Year, Month, Day : UInt16;
      suffix : String;
    begin
      DecodeTime(Now, Hour, Mins, Sec, MSec);
      DecodeDate(Now, Year, Month, Day);
      if Hour < 12 then Suffix := 'AM' else Suffix := 'PM'
      if Hour > 12 then Hour -= 12;
      scriptStartTime := (' ' + toStr(Day) + '-' + toStr(Month) + '-' + toStr(Year) + ' at ' + Padz(IntToStr(Hour), 2) + Padz(IntToStr(Mins), 2) + Suffix);
    end;

    procedure WritetoFile();
    var
      path, str, txt: String;
      theFile, i, j : Integer;
    begin
      try
        path := ScriptPath + theItem + ' ';
        theFile := RewriteFile(path + scriptStartTime + '.csv', False);

        txt := 'Day:,';
        for i := 0 to high(Prices)-1 do
          txt := txt + toStr(i) + ',';
        txt := txt + toStr(high(Prices));

        txt := txt + [URL=https://villavu.com/forum/usertag.php?do=list&action=hash&hash=1]#1[/URL] 3[URL=https://villavu.com/forum/usertag.php?do=list&action=hash&hash=1]#1[/URL] 0 + theItem + ',';   // Writes Prices
        for i := 0 to high(Prices)-1 do
          txt := txt + toStr(Prices[i]) + ',';
        txt := txt + toStr(Prices[high(Prices)]);

        txt := txt + [URL=https://villavu.com/forum/usertag.php?do=list&action=hash&hash=1]#1[/URL] 3[URL=https://villavu.com/forum/usertag.php?do=list&action=hash&hash=1]#1[/URL] 0 + 'MAValue,';
        for i := 0 to high(MAValue)-1 do
          txt := txt + toStr(MAValue[i]) + ',';
        txt := txt + toStr(MAValue[high(Prices)]);

        txt := txt + [URL=https://villavu.com/forum/usertag.php?do=list&action=hash&hash=1]#1[/URL] 3[URL=https://villavu.com/forum/usertag.php?do=list&action=hash&hash=1]#1[/URL] 0 + 'MARec,';
        for i := 0 to high(MARec)-1 do
          txt := txt + toStr(MARec[i]) + ',';
        txt := txt + toStr(MARec[high(Prices)]);

        txt := txt + [URL=https://villavu.com/forum/usertag.php?do=list&action=hash&hash=1]#1[/URL] 3[URL=https://villavu.com/forum/usertag.php?do=list&action=hash&hash=1]#1[/URL] 0 + 'RSIValue,';
        for i := 0 to high(RSIValue)-1 do
          txt := txt + toStr(RSIValue[i]) + ',';
        txt := txt + toStr(RSIValue[high(Prices)]);

        txt := txt + [URL=https://villavu.com/forum/usertag.php?do=list&action=hash&hash=1]#1[/URL] 3[URL=https://villavu.com/forum/usertag.php?do=list&action=hash&hash=1]#1[/URL] 0 + 'RSIRec,';
        for i := 0 to high(RSIRec)-1 do
          txt := txt + toStr(RSIRec[i]) + ',';
        txt := txt + toStr(RSIRec[high(Prices)]);

        txt := txt + [URL=https://villavu.com/forum/usertag.php?do=list&action=hash&hash=1]#1[/URL] 3[URL=https://villavu.com/forum/usertag.php?do=list&action=hash&hash=1]#1[/URL] 0 + 'StoKValue,';
        for i := 0 to high(StoKValue)-1 do
          txt := txt + toStr(StoKValue[i]) + ',';
        txt := txt + toStr(StoKValue[high(Prices)]);

        txt := txt + [URL=https://villavu.com/forum/usertag.php?do=list&action=hash&hash=1]#1[/URL] 3[URL=https://villavu.com/forum/usertag.php?do=list&action=hash&hash=1]#1[/URL] 0 + 'StoDValue,';
        for i := 0 to high(StoDValue)-1 do
          txt := txt + toStr(StoDValue[i]) + ',';
        txt := txt + toStr(StoDValue[high(Prices)]);

        txt := txt + [URL=https://villavu.com/forum/usertag.php?do=list&action=hash&hash=1]#1[/URL] 3[URL=https://villavu.com/forum/usertag.php?do=list&action=hash&hash=1]#1[/URL] 0 + 'StoRec,';
        for i := 0 to high(StoRec)-1 do
          txt := txt + toStr(StoRec[i]) + ',';
        txt := txt + toStr(StoRec[high(Prices)]);

        txt := txt + [URL=https://villavu.com/forum/usertag.php?do=list&action=hash&hash=1]#1[/URL] 3[URL=https://villavu.com/forum/usertag.php?do=list&action=hash&hash=1]#1[/URL] 0 + 'AroonValue,';
        for i := 0 to high(AroonValue)-1 do
          txt := txt + toStr(AroonValue[i]) + ',';
        txt := txt + toStr(AroonValue[high(Prices)]);

        txt := txt + [URL=https://villavu.com/forum/usertag.php?do=list&action=hash&hash=1]#1[/URL] 3[URL=https://villavu.com/forum/usertag.php?do=list&action=hash&hash=1]#1[/URL] 0 + 'AroonRec,';
        for i := 0 to high(AroonRec)-1 do
          txt := txt + toStr(AroonRec[i]) + ',';
        txt := txt + toStr(AroonRec[high(Prices)]);

        txt := txt + [URL=https://villavu.com/forum/usertag.php?do=list&action=hash&hash=1]#1[/URL] 3[URL=https://villavu.com/forum/usertag.php?do=list&action=hash&hash=1]#1[/URL] 0 + 'BollUpper,';
        for i := 0 to high(BollUpper)-1 do
          txt := txt + toStr(BollUpper[i]) + ',';
        txt := txt + toStr(BollUpper[high(Prices)]);

        txt := txt + [URL=https://villavu.com/forum/usertag.php?do=list&action=hash&hash=1]#1[/URL] 3[URL=https://villavu.com/forum/usertag.php?do=list&action=hash&hash=1]#1[/URL] 0 + 'BollLower,';
        for i := 0 to high(BollLower)-1 do
          txt := txt + toStr(BollLower[i]) + ',';
        txt := txt + toStr(BollLower[high(Prices)]);

        txt := txt + [URL=https://villavu.com/forum/usertag.php?do=list&action=hash&hash=1]#1[/URL] 3[URL=https://villavu.com/forum/usertag.php?do=list&action=hash&hash=1]#1[/URL] 0 + 'BollRec,';
        for i := 0 to high(BollRec)-1 do
          txt := txt + toStr(BollRec[i]) + ',';
        txt := txt + toStr(BollRec[high(Prices)]);

        txt := txt + [URL=https://villavu.com/forum/usertag.php?do=list&action=hash&hash=1]#1[/URL] 3[URL=https://villavu.com/forum/usertag.php?do=list&action=hash&hash=1]#1[/URL] 0 + 'TotalRec,';
        for i := 0 to high(TotalRec)-1 do
          txt := txt + toStr(TotalRec[i]) + ',';
        txt := txt + toStr(TotalRec[high(Prices)]);

        WriteFileString(theFile, Txt);
        CloseFile(theFile);
      except
        Writeln('Debug saving - error occurred');
      end;
    end;

    begin
      startTime();
      Setup();
      RS_GetPricesOf(theItem, amountofPrices);
      doMA();
      doRSI();
      doStoch();
      doAroon();
      doBollinger();
      totalScore();
      writetoFile();
    end.
    Last edited by 3Garrett3; 04-04-2015 at 01:56 AM.

    Scripts: Edgeville Chop & Bank, GE Merchanting Aid
    Tutorials: How to Dominate the Grand Exchange

    Quote Originally Posted by YoHoJo View Post
    I like hentai.

  3. #3
    Join Date
    Oct 2014
    Location
    With ezreal~
    Posts
    295
    Mentioned
    45 Post(s)
    Quoted
    255 Post(s)

    Default

    LOOK AT ALL TEH PRETTY PICTURES. OMG OMG OMG!

    This learned me soooo hard.



    It's not gay if it's efficient.

  4. #4
    Join Date
    Aug 2014
    Posts
    167
    Mentioned
    2 Post(s)
    Quoted
    73 Post(s)

    Default

    The converging/diverging trends were neat. Never bothered with long term investments before, so I can say I actually learned something from this, just like good ol' Taric.

  5. #5
    Join Date
    Mar 2013
    Location
    Argentina
    Posts
    758
    Mentioned
    27 Post(s)
    Quoted
    365 Post(s)

    Default

    Quality thread! good! thank you!
    Formerly known as Undorak7

  6. #6
    Join Date
    Dec 2011
    Posts
    69
    Mentioned
    0 Post(s)
    Quoted
    15 Post(s)

    Default

    great guide on merchanting techniques, even has plenty of knowledge applicable outside of RS

    I remember back in 2008ish I was about ready to quit this game for good, but came upon a merchanting clan. It was such a fun time and great community it kept me motivated to keep "playing". I've basically been flipping and bankstanding (or botting) the last 6-7 years and love it, leaves tons of time for other things.

  7. #7
    Join Date
    May 2014
    Posts
    633
    Mentioned
    8 Post(s)
    Quoted
    322 Post(s)

    Default

    Epic guide, do the graph strats work well for the lesser time graphs or is it best to stick to the 6 month ones?

  8. #8
    Join Date
    Feb 2015
    Posts
    49
    Mentioned
    0 Post(s)
    Quoted
    11 Post(s)

    Default

    Holy crap this is amazing. Just read through it all, though I think I'm going to have to read it all again though! Hah.

  9. #9
    Join Date
    Feb 2007
    Location
    Alberta, Canada
    Posts
    4,615
    Mentioned
    50 Post(s)
    Quoted
    429 Post(s)

    Default

    Thanks everyone! I was hoping it would be helpful to people!

    Quote Originally Posted by J_R View Post
    Epic guide, do the graph strats work well for the lesser time graphs or is it best to stick to the 6 month ones?
    You'll notice a lot more trends in long-term graphs, but like the coal one I found, there was about 50 days where it was completely predictable and someone could have made some serious cash noticing a trend like that when it started. The support/resistance levels will still work on the 1 month graphs, it was just harder for me to show "here's a trend AND the result" in 1 month graphs, because once a trend happens it can take a while (a month or more) before it reverses. So you just ride the wave and sell when the time comes and enjoy the profits.

    Scripts: Edgeville Chop & Bank, GE Merchanting Aid
    Tutorials: How to Dominate the Grand Exchange

    Quote Originally Posted by YoHoJo View Post
    I like hentai.

  10. #10
    Join Date
    Sep 2014
    Posts
    55
    Mentioned
    0 Post(s)
    Quoted
    23 Post(s)

    Default

    Great job ! This is like a class in Wall Street.

  11. #11
    Join Date
    Jun 2012
    Posts
    44
    Mentioned
    0 Post(s)
    Quoted
    25 Post(s)

    Default

    Thank you! Really useful, enjoyed reading it and cait wait for part 2 !

  12. #12
    Join Date
    Nov 2011
    Posts
    34
    Mentioned
    0 Post(s)
    Quoted
    0 Post(s)

    Default

    Now I just gotta wait until hopefully Jagex releases graphs/item limits for OSRS.

    Nice Guide.
    First Script - BAMF -[Bam]'s [F]letcher

    New to scripting, more to come ^.^

  13. #13
    Join Date
    May 2013
    Posts
    60
    Mentioned
    0 Post(s)
    Quoted
    29 Post(s)

    Default

    very nice guide bro!!

  14. #14
    Join Date
    Jan 2012
    Location
    Long Island, NY
    Posts
    413
    Mentioned
    5 Post(s)
    Quoted
    95 Post(s)

    Default

    Very well written and useful content, thanks for sharing!

  15. #15
    Join Date
    Dec 2011
    Posts
    45
    Mentioned
    0 Post(s)
    Quoted
    17 Post(s)

    Default

    This is a really good thread and i've been reading it constantly for the past day or so just so I can REALLY grasp how much profit can be made from the grand exchange. I've just been flipping for the time being but I plan on doing some more work with the GE in the future once I make a bit more money

  16. #16
    Join Date
    Mar 2015
    Location
    Australia
    Posts
    101
    Mentioned
    2 Post(s)
    Quoted
    46 Post(s)

    Default

    Amazing thread, consolidated some of the ideas of the g.e that I've been following. Will have to start making my own "resistance/support" graphs!

  17. #17
    Join Date
    Aug 2013
    Posts
    105
    Mentioned
    0 Post(s)
    Quoted
    43 Post(s)

    Default

    Really like this tutorial man! Definitely helps with understanding trends for me anyway

  18. #18
    Join Date
    May 2013
    Posts
    75
    Mentioned
    3 Post(s)
    Quoted
    48 Post(s)

    Default

    In general, does OSRS GE work the same way? (beside some item limits)

  19. #19
    Join Date
    Feb 2007
    Location
    Alberta, Canada
    Posts
    4,615
    Mentioned
    50 Post(s)
    Quoted
    429 Post(s)

    Default

    Quote Originally Posted by MariusK View Post
    In general, does OSRS GE work the same way? (beside some item limits)
    In general, yes. I don't know what the item limits are, but the same pricing methods all apply. I know of several people who flip OSRS and say it works the exact same as RS3.

    Scripts: Edgeville Chop & Bank, GE Merchanting Aid
    Tutorials: How to Dominate the Grand Exchange

    Quote Originally Posted by YoHoJo View Post
    I like hentai.

  20. #20
    Join Date
    Feb 2012
    Posts
    32
    Mentioned
    0 Post(s)
    Quoted
    12 Post(s)

    Default

    Awesome guide. Really helped!

  21. #21
    Join Date
    Feb 2007
    Location
    Alberta, Canada
    Posts
    4,615
    Mentioned
    50 Post(s)
    Quoted
    429 Post(s)

    Default

    A little bump to let you know I've updated the second post with Part 2 - Technical Analysis. I've included lots of pictures and useful code, so I hope everyone finds something useful!

    Scripts: Edgeville Chop & Bank, GE Merchanting Aid
    Tutorials: How to Dominate the Grand Exchange

    Quote Originally Posted by YoHoJo View Post
    I like hentai.

  22. #22
    Join Date
    Aug 2014
    Location
    Australia
    Posts
    932
    Mentioned
    53 Post(s)
    Quoted
    495 Post(s)

    Default

    @3Garrett3 you dirty mathematics loving whore, how goes the [REDACTED]? You must have loved writing this. :P



    New to scripting? Procedures & Functions for Beginners
    Do you use your computer at night? Just get f.lux

  23. #23
    Join Date
    Feb 2007
    Location
    Alberta, Canada
    Posts
    4,615
    Mentioned
    50 Post(s)
    Quoted
    429 Post(s)

    Default

    Quote Originally Posted by Incurable View Post
    @3Garrett3 you dirty mathematics loving whore, how goes the [REDACTED]? You must have loved writing this. :P
    I may or may not have loved it. I cannot confirm or deny these allegations. Also, the project is going alright... except you know me and it's actually being completely rewritten. When it worked (sloppily) it actually had better results than I expected though so WOO.

    Scripts: Edgeville Chop & Bank, GE Merchanting Aid
    Tutorials: How to Dominate the Grand Exchange

    Quote Originally Posted by YoHoJo View Post
    I like hentai.

  24. #24
    Join Date
    Aug 2014
    Location
    Australia
    Posts
    932
    Mentioned
    53 Post(s)
    Quoted
    495 Post(s)

    Default

    Quote Originally Posted by 3Garrett3 View Post
    I may or may not have loved it. I cannot confirm or deny these allegations. Also, the project is going alright... except you know me and it's actually being completely rewritten. When it worked (sloppily) it actually had better results than I expected though so WOO.
    Lmao, is that rewrite number 3 or 4?



    New to scripting? Procedures & Functions for Beginners
    Do you use your computer at night? Just get f.lux

  25. #25
    Join Date
    Feb 2007
    Location
    Alberta, Canada
    Posts
    4,615
    Mentioned
    50 Post(s)
    Quoted
    429 Post(s)

    Default

    Quote Originally Posted by Incurable View Post
    Lmao, is that rewrite number 3 or 4?
    I don't want to talk about it... 3

    Scripts: Edgeville Chop & Bank, GE Merchanting Aid
    Tutorials: How to Dominate the Grand Exchange

    Quote Originally Posted by YoHoJo View Post
    I like hentai.

Page 1 of 2 12 LastLast

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •