作者Efen.bbs@bbs.med.ncku.edu.tw (我~是~胖~子) 看板: plan
標題股市程式碼
時間迴 風 谷 (2004/07/16 Fri 22:21:40) Updated: 2004/08/16
說明:
1.不休市
本股市為24小時不收市,沒有期限,期望值近於零,也就是並非放著就會
保證必定賺錢,而是需要動態的操作。
2.漲跌計算
依照成交量的多寡,而有不同的漲跌機率,當然,愈高就愈有機會上漲,
愈低就愈有機會下跌。
一次的漲跌幅度目前維持在-2%~+5%點之間,會受各股本身的成交量的影響。
3.配額量
每次價格變動後,各股有不同的配額增加(0~5)
4.開盤價
取當天零點過後,第一次變動後的價格為開盤價(目前為0:05)
5.股價變動
目前為每小時變換三次,分別為5、25、45分,各一次
6.成交量
依照實際股市,以買入+賣出的股份為總成交量,每天重新計算一次
7.證交稅
每次賣出時,抽稅百分之十,避免故意拉高成交量及短線交易
8.附有每次變動的股價紀錄、走勢圖(小時為單位)、個人可查詢自己的持股情況
9.每天會產生走勢圖(有總成交量)、股價紀錄
-------------------------------------------------------------------------
: include/global.h
#define BMTA_LOGFILE "run/bmta.log" /* 收外部信的記錄 */
+ #define FN_RUN_STOCK "run/stock" /* 股市資料檔 */
+ #define FN_RUN_STOCK_RECORD "run/stock.record" /* 漲跌紀錄 */
+ #define FN_RUN_STOCK_INFO "run/stock.info" /* 股市走勢 */
: include/struct.h 加入以下這段
#ifdef HAVE_GAME
#define MAXSTOCK 8 /* 八家 */
typedef struct
{
int price[MAXSTOCK]; /* 價格 */
int start[MAXSTOCK]; /* 每日初始價 */
int change[MAXSTOCK]; /* 漲跌 */
int stillnum[MAXSTOCK]; /* 剩餘數量 */
int ordernum[MAXSTOCK]; /* 成交量 */
} STOCK;
#endif
-------------------------------------------------------------------------
: game/stock.c 新增此程式
/*-------------------------------------------------------*/
/* stock.c ( NTHU CS MapleBBS Ver 3.10 ) */
/*-------------------------------------------------------*/
/* target : 股市交易 */
/* create : 04/07/16 */
/* update : 04/07/27 */
/* author : Efen.bbs@bbs.med.ncku.edu.tw */
/* modify : itoc.bbs@bbs.tnfsh.tn.edu.tw */
/*-------------------------------------------------------*/
#include "bbs.h"
#ifdef HAVE_GAME
#define FN_STOCK "stock" /* 個人的股市檔案-各股擁有張數 */
static char stockname[MAXSTOCK][9] =
{
"上 閤 屋", "新 天 地", "遠東百貨", "統聯客運",
"國賓影城", "生活工坊", "寶 雅 館", "成大醫學"
};
static int own[MAXSTOCK];
/*-------------------------------------------------------*/
/* 螢幕控制 */
/*-------------------------------------------------------*/
static void
show_stock_data(sto)
STOCK *sto;
{
int i, change, total, allchange, allordernum, allmoney;
move(2, 0);
outs(" \033[1;42m 編號 \033[36m商店名稱 \033[33m價 格"
"\033[37m(\033[31m漲 \033[32m跌\033[37m) 目前數量 今日成交量"
" 擁有數量 \033[m\n");
outs(" \033[46m◇──────────────────────"
"────────────◇\033[m\n");
total = change = ordernum = allmoney = 0;
for (i = 0; i < MAXSTOCK; i++)
{
change = sto->change[i];
total += sto->price[i];
allchange += change;
allordernum += sto->ordernum[i];
allmoney += own[i] * sto->price[i];
prints("\033[1m%8d.\033[36m%11s \033[3%dm%8d(%s %8d)"
"\033[37m%10d%11d%11d\033[m\n",
i + 1, stockname[i],
change ? (change > 0 ? 1 : 2) : 7,
sto->price[i],
change ? (change > 0 ? "△" : "▽") : "=",
abs(change),
sto->stillnum[i], sto->ordernum[i], own[i]);
}
outs(" \033[46m◇──────────────────────"
"────────────◇\033[m\n");
prints("\033[1;37m 加權股價總指數:\033[3%dm%d %2s %d"
"\033[37m 總成交量:%d\033[m\n\n",
allchange ? (allchange > 0 ? 1 : 2) : 7, total,
allchange ? (allchange > 0 ? "▲" : "▼") : "=", allchange, allordernum);
prints(" \033[1;32;45m您的股價總值:%d 銀幣\033[m\n\n", allmoney);
prints(" \033[1;33;45m您的資本金額:%d 銀幣\033[m", cuser.money);
}
/*-------------------------------------------------------*/
/* 股市指令 */
/*-------------------------------------------------------*/
static void
stock_query(sto)
STOCK *sto;
{
int i;
clear();
outs("\033[1;33m櫃台小姐給您一張清單:\033[\n");
outs("\033[1;32m股市:\033[32m持股一覽表\033[m\n\n");
for (i = 0; i < MAXSTOCK; i++)
{
prints("\033[1;3%dm %d.您擁有 %s 的股份共 %8d 張,股價 [%d]\033[m\n",
i & 7, i, stockname[i], own[i], sto->price[i]);
}
vmsg(NULL);
}
static void
stock_sell(sto)
STOCK *sto;
{
int i, num, money;
char buf[80], ans[8];
sprintf(buf, "要賣哪家(1-%d)?", MAXSTOCK);
vget(b_lines, 0, buf, ans, 2, DOECHO);
i = atoi(ans) - 1;
if (i < 0 || i >= MAXSTOCK)
return;
if (!own[i])
{
vmsg("已無股份可賣");
return;
}
sprintf(buf, "要賣幾張(1-%d)?", own[i]);
vget(b_lines, 0, buf, ans, 5, DOECHO);
num = atoi(ans);
if (num <= 0 || num > own[i])
return;
/* 重新取得目前股市並更新 */
rec_get(FN_RUN_STOCK, sto, sizeof(STOCK), 0);
sto->stillnum[i] += num;
sto->ordernum[i] += num;
rec_put(FN_RUN_STOCK, sto, sizeof(STOCK), 0, NULL);
/* 更新持股 */
own[i] -= num;
usr_fpath(buf, cuser.userid, FN_STOCK);
rec_put(buf, own, sizeof(own), 0, NULL);
money = sto->price[i] * num * 9 / 10; /* 手續費 */
addmoney(money);
sprintf(buf, "賣出 %s %d 張,收入 %d 銀幣!", stockname[i], num, money);
vmsg(buf);
}
static void
stock_buy(sto)
STOCK *sto;
{
int i, num, money;
char buf[80], ans[8];
sprintf(buf, "要買哪家(1-%d)?", MAXSTOCK);
vget(b_lines, 0, buf, ans, 2, DOECHO);
i = atoi(ans) - 1;
if (i < 0 || i >= MAXSTOCK)
return;
if (sto->stillnum[i] <= 0)
{
vmsg("已無股份可買");
return;
}
money = cuser.money / sto->price[i];
sprintf(buf, "要買幾張(1-%d)?", money);
vget(b_lines, 0, buf, ans, 5, DOECHO);
num = atoi(ans);
if (num <= 0 || num > money)
return;
/* 重新取得目前股市 */
rec_get(FN_RUN_STOCK, sto, sizeof(STOCK), 0);
if (sto->stillnum[i] < num)
{
vmsg("股份剛被搶走了,下次請早!");
return;
}
money = sto->price[i] * num;
if (cuser.money < money)
{
vmsg("股價已變動,您不夠金錢購買");
return;
}
/* 更新股市 */
sto->stillnum[i] -= num;
sto->ordernum[i] += num;
rec_put(FN_RUN_STOCK, sto, sizeof(STOCK), 0, NULL);
/* 更新持股 */
own[i] += num;
usr_fpath(buf, cuser.userid, FN_STOCK);
rec_put(buf, own, sizeof(own), 0, NULL);
cuser.money -= money;
sprintf(buf, "買進 %s %d 張,花費 %d 銀幣!", stockname[i], num, money);
vmsg(buf);
}
/*-------------------------------------------------------*/
/* 主程式 */
/*-------------------------------------------------------*/
int
main_stock()
{
int i;
char fpath[64];
STOCK sto;
if (cutmp->status & STATUS_COINLOCK)
{
vmsg(MSG_COINLOCK);
return XEASY;
}
/* 我的持股 */
usr_fpath(fpath, cuser.userid, FN_STOCK);
if (rec_get(fpath, own, sizeof(own), 0))
{
memset(own, 0, sizeof(own));
rec_add(fpath, own, sizeof(STOCK));
}
/* 目前股市 */
if (rec_get(FN_RUN_STOCK, &sto, sizeof(STOCK), 0))
{
for (i = 0; i < MAXSTOCK; i++)
{
sto.price[i] = 100;
sto.start[i] = 100;
sto.change[i] = 0;
sto.stillnum[i] = 100000;
sto.ordernum[i] = 0;
}
rec_add(FN_RUN_STOCK, &sto, sizeof(STOCK));
}
while (1)
{
clear();
outs("\033[1;36;44m ★ ★ ★ ★ \033[31m【 \033[35m證券交易所\033[31m 】"
" \033[36m★ ★ ★ ★ [\033[32mDesign by Efen\033[36m] \033[m");
show_stock_data(&sto);
switch (vans("[B:買 S:賣 C:查詢 F:漲跌紀錄 I:走勢圖 Q:離開]"))
{
case 'c':
stock_query(&sto);
break;
case 'f':
more(FN_RUN_STOCK_RECORD, NULL);
break;
case 'i':
more(FN_RUN_STOCK_INFO, NULL);
break;
case 's':
stock_sell(&sto);
break;
case 'b':
stock_buy(&sto);
break;
case 'q':
return 0;
}
}
}
#endif /* HAVE_GAME */
---------------------------------------------------------------------------
: util/stock-change.c 新增此程式
/*-------------------------------------------------------*/
/* stock-change.c ( NTHU CS MapleBBS Ver 3.10 ) */
/*-------------------------------------------------------*/
/* target : 股市交易變化 */
/* create : 04/07/16 */
/* update : 04/07/27 */
/* author : Efen.bbs@bbs.med.ncku.edu.tw */
/* modify : itoc.bbs@bbs.tnfsh.tn.edu.tw */
/*-------------------------------------------------------*/
#include "bbs.h"
#ifdef HAVE_GAME
#define MAX_LINE 16
static char *fn_tmpfile = "run/stock.change";
static int ordernum = 0;
static char stockname[MAXSTOCK][9] =
{
"上 閤 屋", "新 天 地", "遠東百貨", "統聯客運",
"國賓影城", "生活工坊", "寶 雅 館", "成大醫學"
};
static void
ansi_puts(fp, buf, mode)
FILE *fp;
char *buf, mode;
{
static char state = '0';
if (state != mode)
fprintf(fp, "\033[3%cm", state = mode);
if (*buf)
{
fprintf(fp, buf);
*buf = '\0';
}
}
static void
draw_usies(ptime)
struct tm *ptime;
{
int num, hour, max, min, item, i, j, over;
char buf[ANSILINELEN];
FILE *fp;
int act[24];
for (i = 0; i < 24; i++)
act[i] = 0;
i = 0;
if (fp = fopen(fn_tmpfile, "r"))
{
while ((fscanf(fp, "%d", &num)) != EOF)
{
act[i] = num;
i++;
}
fclose(fp);
}
else
return;
max = act[0];
min = act[0];
for (i = 0; i < 24; i++)
{
if (act[i] > max)
max = act[i];
else if (act[i] < min && act[i] != 0)
min = act[i];
}
min = (min / 100) * 100;
for (i = 0; i < 24; i++)
{
if (act[i] != 0)
act[i] -= min;
}
max -= min;
item = max / MAX_LINE + 1;
over = max > 1000;
fp = fopen(FN_RUN_STOCK_INFO, "w");
fprintf(fp, "\t\t\t\033[1;33;46m [%02d/%02d/%02d] 今日股市走勢 \033[40m\n",
ptime->tm_year % 100, ptime->tm_mon + 1, ptime->tm_mday);
for (i = MAX_LINE + 1; i > 0; i--)
{
strcpy(buf, " ");
for (j = 0; j < 24; j++)
{
max = item * i;
hour = act[j];
if (hour && (max > hour) && (max - item <= hour))
{
ansi_puts(fp, buf, '3');
if (over)
hour = (hour + 5) / 10;
fprintf(fp, "%-3d", hour);
}
else if (max <= hour)
{
ansi_puts(fp, buf, '1');
fprintf(fp, "█ ");
}
else
strcat(buf, " ");
}
fprintf(fp, "\n");
}
fprintf(fp, "\033[34m"
" ╒════════════════════"
"═══════════════╕\n \033[32m"
"0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 "
"15 16 17 18 19 20 21 22 23\n"
"\t%s\t\033[m\n"
"\033[35m基值:\033[37m%-10d\033[35m總成交量:\033[1;37m%d\033[m\n",
over ? "\033[35m單位:\033[37m10\033[m" : "", min, ordernum);
fclose(fp);
if (ptime->tm_hour == 23)
unlink(fn_tmpfile);
}
static int
price_change(sto, i, ordernum) /* 決定股價漲跌 */
STOCK *sto;
int i;
int ordernum;
{
int rate;
/* 此股成交量佔總成交量的比例越高,上漲的機率越高 */
rate = sto->ordernum[i] * 4;
if (rate > ordernum * 3) /* 本股成交量佔大盤 75%~100% */
rate = 101; /* 期望上漲股價 3% */
else if (rate > ordernum * 2) /* 本股成交量佔大盤 50%~74% */
rate = 100; /* 期望上漲股價 2% */
else if (rate > ordernum * 1) /* 本股成交量佔大盤 25%~49% */
rate = 99; /* 期望上漲股價 1% */
else /* 本股成交量佔大盤 0%~24% */
rate = 98; /* 期望上漲股價 0% */
rate = sto->price[i] * (rnd(5) + rate) / 100;
if (rate <= 0)
rate = 1;
sto->change[i] = rate - sto->price[i];
sto->price[i] = rate;
}
int
main()
{
int i, totalprice;
STOCK sto;
time_t now;
struct tm *ptime;
FILE *fp;
now = time(NULL);
ptime = localtime(&now);
chdir(BBSHOME);
/* 取得目前股市 */
rec_get(FN_RUN_STOCK, &sto, sizeof(STOCK), 0);
/* 算總成交量 */
for (i = 0; i < MAXSTOCK; i++)
ordernum += sto.ordernum[i];
/* 更新股市 */
totalprice = 0;
srand(now);
for (i = 0; i < MAXSTOCK; i++)
{
price_change(&sto, i, ordernum);
sto.stillnum[i] += rnd(6);
if (ptime->tm_hour == 0 && ptime->tm_min == 5)
{
sto.start[i] = sto.price[i];
sto.ordernum[i] = 0;
}
totalprice += sto.price[i];
}
rec_put(FN_RUN_STOCK, &sto, sizeof(STOCK), 0, NULL);
/* 寫入漲跌紀錄 */
if (fp = fopen(FN_RUN_STOCK_RECORD, "a"))
{
fprintf(fp, "\033[1;33m%s\033[m\n", Btime(&now));
for (i = 0; i < MAXSTOCK; i++)
fprintf(fp, "%9s", stockname[i]);
fprintf(fp, "\n");
for (i = 0; i < MAXSTOCK; i++)
fprintf(fp, "%8d ", sto.price[i]);
fprintf(fp, "\n\n");
fclose(fp);
}
/* 畫走勢圖 */
if (ptime->tm_min == 5)
{
fp = fopen(fn_tmpfile, "a+");
fprintf(fp, "%d\n", totalprice / 1000);
fclose(fp);
draw_usies(ptime);
}
return 0;
}
#else
int
main()
{
printf("You should define HAVE_GAME first.\n");
return -1;
}
#endif /* HAVE_GAME */
---------------------------------------------------------------------------
: util/account.c
sprintf(title, "%s酸甜苦辣留言板", date);
keeplog(FN_RUN_NOTE_ALL, NULL, title, 2);
+#ifdef HAVE_GAME
+ sprintf(title, "%s股市漲跌紀錄", date);
+ keeplog(FN_RUN_STOCK_RECORD, NULL, title, 2);
+ sprintf(title, "%s股市走勢", date);
+ keeplog(FN_RUN_STOCK_INFO, NULL, title, 0);
+#endif
-------------------------------------------------------------------------
: crontab -e 在最後加入
# 股市變換
5,25,45 * * * * bin/stock-change > /dev/null 2>&1
.....差不多要放下主機管理的工作了....就把這陣子努力的成果跟大家分享囉....
這算是本站最大的一個修修改改想想半自創的程式了吧
--
『╭╯成大醫學╭╯ ◥◢ ﹌ ☆ �i�i bbs.med.ncku.edu.tw �i�i ☆ ﹋
╭╯迴 風 谷╭╯』 ◤◣ →From:140.116.144.137 ←